返回提交历史
Modified
XFEExtension.NetCore.XFEConsole.Test/Program.cs
+24
-5
Modified
XFEExtension.NetCore.XFEConsole/XFEConsole.cs
+57
-5
Modified
XFEExtension.NetCore.XFEConsole/XFEConsoleTextWriter.cs
+37
-37
Modified
XFEExtension.NetCore.XFEConsole/XFEExtension.NetCore.XFEConsole.csproj
+2
-2
Added
XFEExtension.NetCore.XFEConsole/XFEFileLog.cs
+84
-0
Modified
XFEExtension.NetCore.XFEConsole/XFELog.cs
+75
-54
Added
XFEExtension.NetCore.XFEConsole/XFEMemoryLog.cs
+53
-0
XFEstudio/XFEExtension.NetCore.XFEConsole
add-现对日志分为文件日志和内存日志两种类型,分别适用于不同的使用场景 add-日志现已支持逻辑线程安全,在同一个异步操作中的输出不会与其他异步操作的输出交叉
40d5c56
代码差异
7 个文件
+332
-103
@@ -1,6 +1,25 @@
1
using XFEExtension.NetCore.FileExtension;
2
using XFEExtension.NetCore.XFEConsole;
1
using XFEExtension.NetCore.XFEConsole;
3
2
4
var log = new XFELog();
5
log.Import(@"C:\Users\XFEstudio\Documents\2025年01月23日_00时00分00秒至2025年01月30日_23时59分59秒-日志文件.log".ReadOut()!);
6
Console.WriteLine(log.Export());
3
XFEConsole.UseXFEConsoleLog();
4
5
XFEConsole.Log.LogPath = "test.log";
6
7
await Parallel.ForAsync(0, 10000, async (i, ct) =>
8
{
9
await Do(i);
10
});
11
12
//var xFELog = new XFEFileLog();
13
//await Parallel.ForAsync(0, 1000, async (i, ct) =>
14
//{
15
// xFELog.Write($"这是第 {i} 条日志的上半部分", out var isHead);
16
// await Task.Delay(10, ct);
17
// xFELog.WriteLine($",这是第 {i} 条日志的下半部分", out isHead);
18
//});
19
20
async Task Do(int i)
21
{
22
Console.Write($"这是第 {i} 条日志的上半部分");
23
await Task.Delay(10);
24
Console.WriteLine($",这是第 {i} 条日志的下半部分");
25
}
@@ -45,7 +45,7 @@ public static class XFEConsole
45
45
/// <summary>
46
46
/// 当前日志
47
47
/// </summary>
48
public static XFELog Log { get; set; } = new();
48
public static XFELog Log { get; set; } = new XFEFileLog();
49
49
/// <summary>
50
50
/// 客户端列表
51
51
/// </summary>
@@ -77,9 +77,11 @@ public static class XFEConsole
77
77
/// <summary>
78
78
/// 使用XFE控制台日志
79
79
/// </summary>
80
public static void UseXFEConsoleLog(bool autoAddTimeInfo = true, long logTextMaximizeLength = 500000000)
80
public static void UseXFEConsoleLog(bool useMemoryLog = false, bool autoAddTimeInfo = true, long logTextMaximizeLength = -1)
81
81
{
82
82
EnableLog = true;
83
if (useMemoryLog)
84
Log = new XFEMemoryLog();
83
85
Log.AutoAddTimeInfo = autoAddTimeInfo;
84
86
Log.LogTextMaximizeLength = logTextMaximizeLength;
85
87
SetConsoleOutput();
@@ -156,7 +158,57 @@ public static class XFEConsole
156
158
/// </summary>
157
159
/// <param name="text">文本</param>
158
160
/// <returns></returns>
159
public static async Task WriteLine(string? text)
161
public static void WriteLine(string? text)
162
{
163
if (text is not null)
164
{
165
if (ShowInDebug)
166
Debug.WriteLine(text);
167
if (EnableLog)
168
{
169
var log = Log.WriteLine(text, out _);
170
if (ShowInLocalConsole)
171
CurrentConsoleTextWriter?.OriginalTextWriter.WriteLine(log.ToString());
172
}
173
else if (ShowInLocalConsole)
174
{
175
CurrentConsoleTextWriter?.OriginalTextWriter.WriteLine(text);
176
}
177
foreach (var client in ClientList)
178
client.OutputMessage($"[color {ConvertConsoleColorToString(Console.ForegroundColor)} {ConvertConsoleColorToString(Console.BackgroundColor)}]{text}", true).Wait();
179
}
180
}
181
/// <summary>
182
/// 向已连接的XFE控制台输出一条消息
183
/// </summary>
184
/// <param name="text">文本</param>
185
/// <returns></returns>
186
public static void Write(string? text)
187
{
188
if (text is not null)
189
{
190
if (ShowInDebug)
191
Debug.WriteLine(text);
192
if (EnableLog)
193
{
194
var log = Log.Write(text, out var isHead);
195
if (ShowInLocalConsole && !Log.RecordOnlyOnWriteLine)
196
CurrentConsoleTextWriter?.OriginalTextWriter.Write($"{(Log.AutoAddTimeInfo && isHead ? XFELogEntry.TimeToString(log.Time) : string.Empty)}{text}");
197
}
198
else if (ShowInLocalConsole)
199
{
200
CurrentConsoleTextWriter?.OriginalTextWriter.Write(text);
201
}
202
foreach (var client in ClientList)
203
client.OutputMessage($"[color {ConvertConsoleColorToString(Console.ForegroundColor)} {ConvertConsoleColorToString(Console.BackgroundColor)}]{text}", false).Wait();
204
}
205
}
206
/// <summary>
207
/// 向已连接的XFE控制台输出一条消息
208
/// </summary>
209
/// <param name="text">文本</param>
210
/// <returns></returns>
211
public static async Task WriteLineAsync(string? text)
160
212
{
161
213
if (text is not null)
162
214
{
@@ -181,7 +233,7 @@ public static class XFEConsole
181
233
/// </summary>
182
234
/// <param name="text">文本</param>
183
235
/// <returns></returns>
184
public static async Task Write(string? text)
236
public static async Task WriteAsync(string? text)
185
237
{
186
238
if (text is not null)
187
239
{
@@ -190,7 +242,7 @@ public static class XFEConsole
190
242
if (EnableLog)
191
243
{
192
244
var log = Log.Write(text, out var isHead);
193
if (ShowInLocalConsole)
245
if (ShowInLocalConsole && !Log.RecordOnlyOnWriteLine)
194
246
CurrentConsoleTextWriter?.OriginalTextWriter.Write($"{(Log.AutoAddTimeInfo && isHead ? XFELogEntry.TimeToString(log.Time) : string.Empty)}{text}");
195
247
}
196
248
else if (ShowInLocalConsole)
@@ -18,13 +18,13 @@ public class XFEConsoleTextWriter(TextWriter originalTextWriter) : TextWriter
18
18
/// <inheritdoc/>
19
19
public override void Write(bool value)
20
20
{
21
XFEConsole.Write(value.ToString()).Wait();
21
XFEConsole.Write(value.ToString());
22
22
}
23
23
24
24
/// <inheritdoc/>
25
25
public override void Write(char value)
26
26
{
27
XFEConsole.Write(value.ToString()).Wait();
27
XFEConsole.Write(value.ToString());
28
28
}
29
29
30
30
/// <inheritdoc/>
@@ -37,7 +37,7 @@ public class XFEConsoleTextWriter(TextWriter originalTextWriter) : TextWriter
37
37
{
38
38
stringBuilder.Append(sigChar);
39
39
}
40
XFEConsole.Write(stringBuilder.ToString()).Wait();
40
XFEConsole.Write(stringBuilder.ToString());
41
41
}
42
42
}
43
43
@@ -48,74 +48,74 @@ public class XFEConsoleTextWriter(TextWriter originalTextWriter) : TextWriter
48
48
{
49
49
var stringBuilder = new StringBuilder();
50
50
stringBuilder.Append(buffer[i]);
51
XFEConsole.Write(stringBuilder.ToString()).Wait();
51
XFEConsole.Write(stringBuilder.ToString());
52
52
}
53
53
}
54
54
55
55
/// <inheritdoc/>
56
56
public override void Write(decimal value)
57
57
{
58
XFEConsole.Write(value.ToString()).Wait();
58
XFEConsole.Write(value.ToString());
59
59
}
60
60
61
61
/// <inheritdoc/>
62
62
public override void Write(double value)
63
63
{
64
XFEConsole.Write(value.ToString()).Wait();
64
XFEConsole.Write(value.ToString());
65
65
}
66
66
67
67
/// <inheritdoc/>
68
68
public override void Write(int value)
69
69
{
70
XFEConsole.Write(value.ToString()).Wait();
70
XFEConsole.Write(value.ToString());
71
71
}
72
72
73
73
/// <inheritdoc/>
74
74
public override void Write(long value)
75
75
{
76
XFEConsole.Write(value.ToString()).Wait();
76
XFEConsole.Write(value.ToString());
77
77
}
78
78
79
79
/// <inheritdoc/>
80
80
public override void Write(object? value)
81
81
{
82
XFEConsole.Write(value?.ToString()).Wait();
82
XFEConsole.Write(value?.ToString());
83
83
}
84
84
85
85
/// <inheritdoc/>
86
86
public override void Write(float value)
87
87
{
88
XFEConsole.Write(value.ToString()).Wait();
88
XFEConsole.Write(value.ToString());
89
89
}
90
90
91
91
/// <inheritdoc/>
92
92
public override void Write(string? value)
93
93
{
94
XFEConsole.Write(value).Wait();
94
XFEConsole.Write(value);
95
95
}
96
96
97
97
/// <inheritdoc/>
98
98
public override void Write(StringBuilder? value)
99
99
{
100
XFEConsole.Write(value?.ToString()).Wait();
100
XFEConsole.Write(value?.ToString());
101
101
}
102
102
103
103
/// <inheritdoc/>
104
104
public override void Write(uint value)
105
105
{
106
XFEConsole.Write(value.ToString()).Wait();
106
XFEConsole.Write(value.ToString());
107
107
}
108
108
109
109
/// <inheritdoc/>
110
110
public override void Write(ulong value)
111
111
{
112
XFEConsole.Write(value.ToString()).Wait();
112
XFEConsole.Write(value.ToString());
113
113
}
114
114
115
115
/// <inheritdoc/>
116
116
public override async Task WriteAsync(char value)
117
117
{
118
await XFEConsole.Write(value.ToString());
118
await XFEConsole.WriteAsync(value.ToString());
119
119
}
120
120
121
121
/// <inheritdoc/>
@@ -125,32 +125,32 @@ public class XFEConsoleTextWriter(TextWriter originalTextWriter) : TextWriter
125
125
{
126
126
var stringBuilder = new StringBuilder();
127
127
stringBuilder.Append(buffer[i]);
128
await XFEConsole.Write(stringBuilder.ToString());
128
await XFEConsole.WriteAsync(stringBuilder.ToString());
129
129
}
130
130
}
131
131
132
132
/// <inheritdoc/>
133
133
public override async Task WriteAsync(string? value)
134
134
{
135
await XFEConsole.Write(value);
135
await XFEConsole.WriteAsync(value);
136
136
}
137
137
138
138
/// <inheritdoc/>
139
139
public override void WriteLine()
140
140
{
141
XFEConsole.WriteLine("").Wait();
141
XFEConsole.WriteLine("");
142
142
}
143
143
144
144
/// <inheritdoc/>
145
145
public override void WriteLine(bool value)
146
146
{
147
XFEConsole.WriteLine(value.ToString()).Wait();
147
XFEConsole.WriteLine(value.ToString());
148
148
}
149
149
150
150
/// <inheritdoc/>
151
151
public override void WriteLine(char value)
152
152
{
153
XFEConsole.WriteLine(value.ToString()).Wait();
153
XFEConsole.WriteLine(value.ToString());
154
154
}
155
155
156
156
/// <inheritdoc/>
@@ -163,7 +163,7 @@ public class XFEConsoleTextWriter(TextWriter originalTextWriter) : TextWriter
163
163
{
164
164
stringBuilder.Append(sigChar);
165
165
}
166
XFEConsole.WriteLine(stringBuilder.ToString()).Wait();
166
XFEConsole.WriteLine(stringBuilder.ToString());
167
167
}
168
168
}
169
169
@@ -174,85 +174,85 @@ public class XFEConsoleTextWriter(TextWriter originalTextWriter) : TextWriter
174
174
{
175
175
var stringBuilder = new StringBuilder();
176
176
stringBuilder.Append(buffer[i]);
177
XFEConsole.WriteLine(stringBuilder.ToString()).Wait();
177
XFEConsole.WriteLine(stringBuilder.ToString());
178
178
}
179
179
}
180
180
181
181
/// <inheritdoc/>
182
182
public override void WriteLine(decimal value)
183
183
{
184
XFEConsole.WriteLine(value.ToString()).Wait();
184
XFEConsole.WriteLine(value.ToString());
185
185
}
186
186
187
187
/// <inheritdoc/>
188
188
public override void WriteLine(double value)
189
189
{
190
XFEConsole.WriteLine(value.ToString()).Wait();
190
XFEConsole.WriteLine(value.ToString());
191
191
}
192
192
193
193
/// <inheritdoc/>
194
194
public override void WriteLine(int value)
195
195
{
196
XFEConsole.WriteLine(value.ToString()).Wait();
196
XFEConsole.WriteLine(value.ToString());
197
197
}
198
198
199
199
/// <inheritdoc/>
200
200
public override void WriteLine(long value)
201
201
{
202
XFEConsole.WriteLine(value.ToString()).Wait();
202
XFEConsole.WriteLine(value.ToString());
203
203
}
204
204
205
205
/// <inheritdoc/>
206
206
public override void WriteLine(object? value)
207
207
{
208
208
if (value is Exception exception)
209
XFEConsole.WriteLine($"[foldblock color: white #ff0000 title: 错误:{exception.Message} text: {exception}]").Wait();
209
XFEConsole.WriteLine($"[foldblock color: white #ff0000 title: 错误:{exception.Message} text: {exception}]");
210
210
if (XFEConsole.AutoAnalyzeObject)
211
211
XFEConsole.WriteObject(value).Wait();
212
212
else
213
XFEConsole.WriteLine(value?.ToString()).Wait();
213
XFEConsole.WriteLine(value?.ToString());
214
214
}
215
215
216
216
/// <inheritdoc/>
217
217
public override void WriteLine(float value)
218
218
{
219
XFEConsole.WriteLine(value.ToString()).Wait();
219
XFEConsole.WriteLine(value.ToString());
220
220
}
221
221
222
222
/// <inheritdoc/>
223
223
public override void WriteLine(string? value)
224
224
{
225
XFEConsole.WriteLine(value).Wait();
225
XFEConsole.WriteLine(value);
226
226
}
227
227
228
228
/// <inheritdoc/>
229
229
public override void WriteLine(StringBuilder? value)
230
230
{
231
XFEConsole.WriteLine(value?.ToString()).Wait();
231
XFEConsole.WriteLine(value?.ToString());
232
232
}
233
233
234
234
/// <inheritdoc/>
235
235
public override void WriteLine(uint value)
236
236
{
237
XFEConsole.WriteLine(value.ToString()).Wait();
237
XFEConsole.WriteLine(value.ToString());
238
238
}
239
239
240
240
/// <inheritdoc/>
241
241
public override void WriteLine(ulong value)
242
242
{
243
XFEConsole.WriteLine(value.ToString()).Wait();
243
XFEConsole.WriteLine(value.ToString());
244
244
}
245
245
246
246
/// <inheritdoc/>
247
247
public override async Task WriteLineAsync()
248
248
{
249
await XFEConsole.WriteLine("");
249
await XFEConsole.WriteLineAsync("");
250
250
}
251
251
252
252
/// <inheritdoc/>
253
253
public override async Task WriteLineAsync(char value)
254
254
{
255
await XFEConsole.WriteLine(value.ToString());
255
await XFEConsole.WriteLineAsync(value.ToString());
256
256
}
257
257
258
258
/// <inheritdoc/>
@@ -262,13 +262,13 @@ public class XFEConsoleTextWriter(TextWriter originalTextWriter) : TextWriter
262
262
{
263
263
var stringBuilder = new StringBuilder();
264
264
stringBuilder.Append(buffer[i]);
265
await XFEConsole.WriteLine(stringBuilder.ToString());
265
await XFEConsole.WriteLineAsync(stringBuilder.ToString());
266
266
}
267
267
}
268
268
269
269
/// <inheritdoc/>
270
270
public override async Task WriteLineAsync(string? value)
271
271
{
272
await XFEConsole.WriteLine(value);
272
await XFEConsole.WriteLineAsync(value);
273
273
}
274
274
}
@@ -4,7 +4,7 @@
4
4
<TargetFramework>net8.0</TargetFramework>
5
5
<ImplicitUsings>enable</ImplicitUsings>
6
6
<Nullable>enable</Nullable>
7
<Version>1.1.2</Version>
7
<Version>1.2.0</Version>
8
8
<Authors>XFEstudio</Authors>
9
9
<Company>寰宇朽力网络科技</Company>
10
10
<Description>XFEConsole是一个可以运行用户进行远程输出的调试辅助工具,需要配合XFE工具箱来使用,当然也可以根据本DLL内的架构搭建一个调试工具</Description>
@@ -14,7 +14,7 @@
14
14
<PackageReadmeFile>README.md</PackageReadmeFile>
15
15
<RepositoryUrl>https://github.com/XFEstudio/XFEExtension.NetCore.XFEConsole.git</RepositoryUrl>
16
16
<PackageTags>XFE;Console;Test;Out;Output;Remote;</PackageTags>
17
<PackageReleaseNotes>进一步修复了日志记录中出现中括号导致的截断问题</PackageReleaseNotes>
17
<PackageReleaseNotes>现对日志分为文件日志和内存日志两种类型,分别适用于不同的使用场景;日志现已支持逻辑线程安全,在同一个异步操作中的输出不会与其他异步操作的输出交叉</PackageReleaseNotes>
18
18
<PackageLicenseFile>LICENSE</PackageLicenseFile>
19
19
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
20
20
<Title>XFEExtension.NetCore.XFEConsole</Title>
@@ -0,0 +1,84 @@
1
2
using System.Text;
3
4
namespace XFEExtension.NetCore.XFEConsole;
5
6
/// <summary>
7
/// XFE文件日志
8
/// </summary>
9
public class XFEFileLog : XFELog
10
{
11
/// <summary>
12
/// 当前日志文件流
13
/// </summary>
14
public FileStream? CurrentLogFileStream { get; set; }
15
16
/// <inheritdoc/>
17
public override List<XFELogEntry> Logs
18
{
19
get
20
{
21
return ImportFromText(Export());
22
}
23
protected set => base.Logs = value;
24
}
25
26
/// <inheritdoc/>
27
public override string LogPath
28
{
29
get => base.LogPath;
30
set
31
{
32
base.LogPath = value;
33
CurrentLogFileStream?.Dispose();
34
CurrentLogFileStream = null;
35
}
36
}
37
38
/// <summary>
39
/// XFE文件日志
40
/// </summary>
41
public XFEFileLog() => Current = this;
42
43
/// <inheritdoc/>
44
public override void AddLog(XFELogEntry xFELogEntry)
45
{
46
if (CurrentLogFileStream is null)
47
{
48
CurrentLogFileStream = new FileStream(LogPath, FileMode.OpenOrCreate, FileAccess.Write, FileShare.Read);
49
CurrentLogFileStream.Seek(0, SeekOrigin.End);
50
}
51
CurrentLogFileStream.Write(Encoding.UTF8.GetBytes(xFELogEntry.ToString(Converters) + Environment.NewLine));
52
CurrentLogFileStream.Flush();
53
}
54
55
/// <inheritdoc/>
56
public override string Export() => File.ReadAllText(LogPath);
57
58
/// <inheritdoc/>
59
public override string Export(DateTime startDateTime, DateTime endDateTime)
60
{
61
var allLogs = Export();
62
var logs = ImportFromText(allLogs);
63
var filteredLogs = logs.Where(log => log.Time >= startDateTime && log.Time <= endDateTime);
64
return string.Join("\n", filteredLogs.Select(log => log.ToString(Converters)));
65
}
66
67
/// <inheritdoc/>
68
public override string ExportOriginal() => string.Join("\n", Logs.Select(log => log.ToString()));
69
70
/// <inheritdoc/>
71
public override void Import(string logText)
72
{
73
CurrentLogFileStream ??= new FileStream(LogPath, FileMode.OpenOrCreate, FileAccess.Write, FileShare.Read);
74
CurrentLogFileStream.Write(Encoding.UTF8.GetBytes(logText + Environment.NewLine));
75
}
76
77
/// <inheritdoc/>
78
public override void Clear()
79
{
80
CurrentLogFileStream ??= new FileStream(LogPath, FileMode.OpenOrCreate, FileAccess.Write, FileShare.Read);
81
CurrentLogFileStream.SetLength(0);
82
CurrentLogFileStream.Flush();
83
}
84
}
@@ -5,13 +5,12 @@ namespace XFEExtension.NetCore.XFEConsole;
5
5
/// <summary>
6
6
/// XFE日志
7
7
/// </summary>
8
public class XFELog
8
public abstract class XFELog
9
9
{
10
private bool _isHead = true;
11
10
/// <summary>
12
11
/// 自动添加时间信息
13
12
/// </summary>
14
public bool AutoAddTimeInfo { get; set; } = false;
13
public bool AutoAddTimeInfo { get; set; } = true;
15
14
/// <summary>
16
15
/// 使用缓存,并在WriteLine时记录日志
17
16
/// </summary>
@@ -19,7 +18,7 @@ public class XFELog
19
18
/// <summary>
20
19
/// Log日志文件长度上限
21
20
/// </summary>
22
public long LogTextMaximizeLength { get; set; } = 500000000;
21
public long LogTextMaximizeLength { get; set; } = -1;
23
22
/// <summary>
24
23
/// 当前日志文本长度
25
24
/// </summary>
@@ -36,7 +35,7 @@ public class XFELog
36
35
/// <summary>
37
36
/// 日志路径
38
37
/// </summary>
39
public string LogPath { get; set; } = "Log";
38
public virtual string LogPath { get; set; } = $"{DateTime.Now:yyyy-MM-dd_HH-mm-ss}.log";
40
39
/// <summary>
41
40
/// 当前日志
42
41
/// </summary>
@@ -44,68 +43,51 @@ public class XFELog
44
43
/// <summary>
45
44
/// 缓存日志
46
45
/// </summary>
47
public XFELogEntry CacheLog { get; set; } = new();
46
public static AsyncLocal<XFELogEntry?> CacheLog { get; set; } = new();
48
47
/// <summary>
49
48
/// 日志条目
50
49
/// </summary>
51
public List<XFELogEntry> Logs { get; set; } = [];
50
public virtual List<XFELogEntry> Logs { get; protected set; } = [];
52
51
/// <summary>
53
52
/// 日志特殊字符的转换器(如回车,换行等)
54
53
/// </summary>
55
54
public EscapeConverter[] Converters { get; set; } = [new("\n", "\\n", "n", "\\"), new("\r", "\\r", "r", "\\")];
56
/// <summary>
57
/// XFE日志
58
/// </summary>
59
public XFELog() => Current = this;
60
private void RemoveOverflow()
61
{
62
var currentLength = CurrentLogsTextLength;
63
while (currentLength > LogTextMaximizeLength)
64
{
65
currentLength -= Logs[0].LogText.Length;
66
Logs.RemoveAt(0);
67
}
68
}
55
69
56
/// <summary>
70
57
/// 添加一条日志
71
58
/// </summary>
72
59
/// <param name="xFELogEntry">日志条目</param>
73
public void AddLog(XFELogEntry xFELogEntry)
74
{
75
Logs.Add(xFELogEntry);
76
RemoveOverflow();
77
}
60
public abstract void AddLog(XFELogEntry xFELogEntry);
61
78
62
/// <summary>
79
63
/// 导出当前全部日志为文本
80
64
/// </summary>
81
65
/// <returns>日志文本</returns>
82
public string Export() => string.Join("\n", Logs.Select(log => log.ToString(Converters)));
66
public abstract string Export();
67
83
68
/// <summary>
84
69
/// 导出指定日期区间的日志为文本
85
70
/// </summary>
86
71
/// <returns>日志文本</returns>
87
public string Export(DateTime startDateTime, DateTime endDateTime) => string.Join("\n", Logs.Where(log => log.Time >= startDateTime && log.Time <= endDateTime).Select(log => log.ToString(Converters)));
72
public abstract string Export(DateTime startDateTime, DateTime endDateTime);
73
88
74
/// <summary>
89
75
/// 导出当前全部日志原文为文本
90
76
/// </summary>
91
77
/// <returns>日志文本</returns>
92
public string ExportOriginal() => string.Join("\n", Logs.Select(log => log.ToString()));
78
public abstract string ExportOriginal();
79
93
80
/// <summary>
94
81
/// 导入日志
95
82
/// </summary>
96
83
/// <param name="logText">日志文本</param>
97
public void Import(string logText)
98
{
99
foreach (var log in logText.Split('\n', StringSplitOptions.RemoveEmptyEntries))
100
{
101
if (log is not null && XFELogEntry.FromString(log, Converters) is XFELogEntry xFELogEntry)
102
AddLog(xFELogEntry);
103
}
104
}
84
public abstract void Import(string logText);
85
105
86
/// <summary>
106
87
/// 清除全部日志
107
88
/// </summary>
108
public void Clear() => Logs.Clear();
89
public abstract void Clear();
90
109
91
/// <summary>
110
92
/// 添加一条日志
111
93
/// </summary>
@@ -124,6 +106,7 @@ public class XFELog
124
106
AddLog(entry);
125
107
return entry;
126
108
}
109
127
110
/// <summary>
128
111
/// 添加一条日志
129
112
/// </summary>
@@ -131,6 +114,7 @@ public class XFELog
131
114
/// <param name="logLevel">日志级别</param>
132
115
/// <returns>日志条目</returns>
133
116
public XFELogEntry AddLog(string logText, LogLevel logLevel = LogLevel.Info) => AddLog(logText, DateTime.Now, logLevel);
117
134
118
/// <summary>
135
119
/// 记录
136
120
/// </summary>
@@ -139,16 +123,15 @@ public class XFELog
139
123
/// <returns></returns>
140
124
public XFELogEntry Write(string logText, out bool isHead)
141
125
{
142
isHead = _isHead;
143
_isHead = false;
144
var logLevel = isHead ? LogLevel.Info : CacheLog.Level;
126
isHead = CacheLog.Value is null;
127
var logLevel = isHead ? LogLevel.Info : CacheLog.Value!.Level;
145
128
try
146
129
{
147
130
var split = logText.Split(['[', ']'], StringSplitOptions.RemoveEmptyEntries);
148
131
if (split.Length > 1)
149
132
{
150
133
if (!TryConverterToLogLevel(split[0], out logLevel))
151
logLevel = isHead ? LogLevel.Info : CacheLog.Level;
134
logLevel = isHead ? LogLevel.Info : CacheLog.Value!.Level;
152
135
else
153
136
logText = split[1];
154
137
}
@@ -158,18 +141,25 @@ public class XFELog
158
141
{
159
142
if (isHead)
160
143
{
161
CacheLog = AddLog(logText, logLevel);
162
return CacheLog;
144
var log = new XFELogEntry
145
{
146
Time = DateTime.Now,
147
Level = logLevel,
148
LogText = logText
149
};
150
CacheLog.Value = log;
151
return log;
163
152
}
164
CacheLog.Level = logLevel;
165
CacheLog.LogText += logText;
166
return CacheLog;
153
CacheLog.Value!.Level = logLevel;
154
CacheLog.Value!.LogText += logText;
155
return CacheLog.Value;
167
156
}
168
157
else
169
158
{
170
159
return AddLog(logText, logLevel);
171
160
}
172
161
}
162
173
163
/// <summary>
174
164
/// 记录一行
175
165
/// </summary>
@@ -178,9 +168,8 @@ public class XFELog
178
168
/// <returns></returns>
179
169
public XFELogEntry WriteLine(string logText, out bool isHead)
180
170
{
181
isHead = _isHead;
182
_isHead = true;
183
var logLevel = isHead ? LogLevel.Info : CacheLog.Level;
171
isHead = CacheLog.Value is null;
172
var logLevel = isHead ? LogLevel.Info : CacheLog.Value!.Level;
184
173
try
185
174
{
186
175
var split = logText.Split(['[', ']'], StringSplitOptions.RemoveEmptyEntries);
@@ -188,7 +177,7 @@ public class XFELog
188
177
{
189
178
if (!TryConverterToLogLevel(split[0], out logLevel))
190
179
{
191
logLevel = isHead ? LogLevel.Info : CacheLog.Level;
180
logLevel = isHead ? LogLevel.Info : CacheLog.Value!.Level;
192
181
}
193
182
else
194
183
{
@@ -209,16 +198,29 @@ public class XFELog
209
198
if (RecordOnlyOnWriteLine)
210
199
{
211
200
if (isHead)
212
return AddLog(logText, logLevel);
213
CacheLog.Level = logLevel;
214
CacheLog.LogText += logText;
215
return CacheLog;
201
{
202
var log = new XFELogEntry
203
{
204
Time = DateTime.Now,
205
Level = logLevel,
206
LogText = logText
207
};
208
CacheLog.Value = null;
209
return log;
210
}
211
CacheLog.Value!.Level = logLevel;
212
CacheLog.Value!.LogText += logText;
213
var returnLog = CacheLog.Value;
214
CacheLog.Value = null;
215
AddLog(returnLog);
216
return returnLog;
216
217
}
217
218
else
218
219
{
219
220
return AddLog(logText, logLevel);
220
221
}
221
222
}
223
222
224
/// <summary>
223
225
/// 尝试转换为警示等级
224
226
/// </summary>
@@ -252,4 +254,23 @@ public class XFELog
252
254
return false;
253
255
}
254
256
}
257
258
/// <summary>
259
/// 从文本导入日志
260
/// </summary>
261
/// <param name="logText"></param>
262
/// <param name="converters"></param>
263
/// <returns></returns>
264
public static List<XFELogEntry> ImportFromText(string logText, params EscapeConverter[] converters)
265
{
266
var logs = new List<XFELogEntry>();
267
if (converters.Length == 0)
268
converters = [new("\n", "\\n", "n", "\\"), new("\r", "\\r", "r", "\\")];
269
foreach (var log in logText.Split('\n', StringSplitOptions.RemoveEmptyEntries))
270
{
271
if (log is not null && XFELogEntry.FromString(log, converters) is XFELogEntry xFELogEntry)
272
logs.Add(xFELogEntry);
273
}
274
return logs;
275
}
255
276
}
@@ -0,0 +1,53 @@
1
namespace XFEExtension.NetCore.XFEConsole;
2
3
/// <summary>
4
/// XFE内存日志
5
/// </summary>
6
public class XFEMemoryLog : XFELog
7
{
8
/// <summary>
9
/// XFE内存日志
10
/// </summary>
11
public XFEMemoryLog() => Current = this;
12
13
/// <inheritdoc/>
14
public override string Export() => string.Join("\n", Logs.Select(log => log.ToString(Converters)));
15
16
/// <inheritdoc/>
17
public override string Export(DateTime startDateTime, DateTime endDateTime) => string.Join("\n", Logs.Where(log => log.Time >= startDateTime && log.Time <= endDateTime).Select(log => log.ToString(Converters)));
18
19
/// <summary>
20
/// 移除超出长度限制的日志
21
/// </summary>
22
private void RemoveOverflow()
23
{
24
if (LogTextMaximizeLength == -1)
25
return;
26
var currentLength = CurrentLogsTextLength;
27
while (currentLength > LogTextMaximizeLength)
28
{
29
currentLength -= Logs[0].LogText.Length;
30
Logs.RemoveAt(0);
31
}
32
}
33
34
/// <inheritdoc/>
35
public override void AddLog(XFELogEntry xFELogEntry)
36
{
37
Logs.Add(xFELogEntry);
38
RemoveOverflow();
39
}
40
41
/// <inheritdoc/>
42
public override string ExportOriginal() => string.Join("\n", Logs.Select(log => log.ToString()));
43
44
/// <inheritdoc/>
45
public override void Import(string logText)
46
{
47
var logs = ImportFromText(logText);
48
Logs.AddRange(logs);
49
}
50
51
/// <inheritdoc/>
52
public override void Clear() => Logs.Clear();
53
}