XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet
公开
关注 0 Fork 0 Star 0
返回提交历史

XFEstudio/XFEExtension.NetCore.XFEConsole

add-现对日志分为文件日志和内存日志两种类型,分别适用于不同的使用场景 add-日志现已支持逻辑线程安全,在同一个异步操作中的输出不会与其他异步操作的输出交叉

40d5c56
XFE工作室室长 <mail@xfegzs.com>
提交于

代码差异

7 个文件 +332 -103
Modified XFEExtension.NetCore.XFEConsole.Test/Program.cs +24 -5
@@ -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 }
Modified XFEExtension.NetCore.XFEConsole/XFEConsole.cs +57 -5
@@ -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)
Modified XFEExtension.NetCore.XFEConsole/XFEConsoleTextWriter.cs +37 -37
@@ -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 }
Modified XFEExtension.NetCore.XFEConsole/XFEExtension.NetCore.XFEConsole.csproj +2 -2
@@ -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>
Added XFEExtension.NetCore.XFEConsole/XFEFileLog.cs +84 -0
@@ -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 }
Modified XFEExtension.NetCore.XFEConsole/XFELog.cs +75 -54
@@ -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 }
Added XFEExtension.NetCore.XFEConsole/XFEMemoryLog.cs +53 -0
@@ -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 }