Skip to content

Commit bc84e75

Browse files
authored
Merge pull request #23 from dotnet-campus/t/walterlv/write-line
防止 Console.WriteLine 出现的异常致日志系统错误
2 parents 085c0e3 + 14a20f9 commit bc84e75

File tree

4 files changed

+37
-17
lines changed

4 files changed

+37
-17
lines changed

src/dotnetCampus.Logger/Writers/ConsoleLogger.cs

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ public class ConsoleLogger : ILogger
2626
/// <param name="threadMode">指定控制台日志的线程安全模式。</param>
2727
/// <param name="mainArgs">Main 方法的参数。</param>
2828
public ConsoleLogger(LogWritingThreadMode threadMode = LogWritingThreadMode.NotThreadSafe, string[]? mainArgs = null)
29-
: this(threadMode.CreateCoreLogWriter(), TagFilterManager.FromCommandLineArgs(mainArgs ?? []))
29+
: this(threadMode.CreateCoreLogWriter(SafeWriteLine), TagFilterManager.FromCommandLineArgs(mainArgs ?? []))
3030
{
3131
}
3232

@@ -127,18 +127,35 @@ private void ConsoleMultilineMessage(string message, Func<string, string?> forma
127127
{
128128
if (forceSingleLine || !message.Contains('\n'))
129129
{
130-
Console.WriteLine(formatter(message));
130+
SafeWriteLine(formatter(message));
131131
}
132132
else
133133
{
134134
using var reader = new StringReader(message);
135135
while (reader.ReadLine() is { } line)
136136
{
137-
Console.WriteLine(formatter(line));
137+
SafeWriteLine(formatter(line));
138138
}
139139
}
140140
}
141141

142+
/// <summary>
143+
/// 安全地写入一行日志,避免出现 IO 异常。
144+
/// </summary>
145+
/// <param name="message"></param>
146+
internal static void SafeWriteLine(string? message)
147+
{
148+
try
149+
{
150+
Console.WriteLine(message);
151+
}
152+
catch (IOException)
153+
{
154+
// 如果写入日志时发生 IO 异常,已经没有办法救活了。
155+
// 这是日志系统的内部实现,所以日志也记不了了,汗……
156+
}
157+
}
158+
142159
/// <summary>
143160
/// 清空当前行并移动光标到上一行。
144161
/// </summary>

src/dotnetCampus.Logger/Writers/ConsoleLoggerBuilder.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ namespace dotnetCampus.Logging.Writers;
99
public sealed class ConsoleLoggerBuilder
1010
{
1111
private TagFilterManager? _tagFilterManager;
12-
private ICoreLogWriter _coreWriter = new NotThreadSafeLogWriter();
12+
private ICoreLogWriter _coreWriter = new NotThreadSafeLogWriter(ConsoleLogger.SafeWriteLine);
1313

1414
/// <summary>
1515
/// 高于或等于此级别的日志才会被记录。
@@ -35,9 +35,9 @@ public ConsoleLoggerBuilder WithThreadSafe(LogWritingThreadMode threadMode)
3535
{
3636
_coreWriter = threadMode switch
3737
{
38-
LogWritingThreadMode.NotThreadSafe => new NotThreadSafeLogWriter(),
39-
LogWritingThreadMode.Lock => new LockLogWriter(),
40-
LogWritingThreadMode.ProducerConsumer => new ProducerConsumerLogWriter(),
38+
LogWritingThreadMode.NotThreadSafe => new NotThreadSafeLogWriter(ConsoleLogger.SafeWriteLine),
39+
LogWritingThreadMode.Lock => new LockLogWriter(ConsoleLogger.SafeWriteLine),
40+
LogWritingThreadMode.ProducerConsumer => new ProducerConsumerLogWriter(ConsoleLogger.SafeWriteLine),
4141
_ => throw new ArgumentOutOfRangeException(nameof(threadMode)),
4242
};
4343
return this;

src/dotnetCampus.Logger/Writers/Helpers/ICoreLogWriter.cs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,14 @@ internal interface ICoreLogWriter
2525
/// <summary>
2626
/// 不处理线程安全问题的日志写入器。
2727
/// </summary>
28-
internal sealed class NotThreadSafeLogWriter : ICoreLogWriter
28+
internal sealed class NotThreadSafeLogWriter(Action<string> logger) : ICoreLogWriter
2929
{
3030
/// <inheritdoc />
3131
public void Write(string? message)
3232
{
3333
if (message is not null)
3434
{
35-
Console.WriteLine(message);
35+
logger(message);
3636
}
3737
}
3838

@@ -46,7 +46,7 @@ public void Do(Action action)
4646
/// <summary>
4747
/// 使用锁来保证线程安全的日志写入器。
4848
/// </summary>
49-
internal sealed class LockLogWriter : ICoreLogWriter
49+
internal sealed class LockLogWriter(Action<string> logger) : ICoreLogWriter
5050
{
5151
private readonly object _lock = new();
5252

@@ -57,7 +57,7 @@ public void Write(string? message)
5757
{
5858
lock (_lock)
5959
{
60-
Console.WriteLine(message);
60+
logger(message);
6161
}
6262
}
6363
}
@@ -77,13 +77,15 @@ public void Do(Action action)
7777
/// </summary>
7878
internal sealed class ProducerConsumerLogWriter : ICoreLogWriter
7979
{
80+
private readonly Action<string> _logger;
8081
private readonly BlockingCollection<object> _queue = new();
8182

8283
/// <summary>
8384
/// 创建 <see cref="ProducerConsumerLogWriter"/> 的新实例,并启动消费线程。
8485
/// </summary>
85-
public ProducerConsumerLogWriter()
86+
public ProducerConsumerLogWriter(Action<string> logger)
8687
{
88+
_logger = logger;
8789
new Task(Consume, TaskCreationOptions.LongRunning).Start();
8890
}
8991

@@ -112,7 +114,7 @@ private void Consume()
112114
switch (item)
113115
{
114116
case string message:
115-
Console.WriteLine(message);
117+
_logger(message);
116118
break;
117119
case Action action:
118120
action();

src/dotnetCampus.Logger/Writers/LogWritingThreadMode.cs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,14 @@ internal static class LogWritingThreadModeExtensions
3636
/// 根据 <see cref="LogWritingThreadMode"/> 创建对应的 <see cref="ICoreLogWriter"/> 实例。
3737
/// </summary>
3838
/// <param name="threadMode">线程安全模式。</param>
39+
/// <param name="logger">实际的日志写入方法。</param>
3940
/// <returns>最终日志写入器。</returns>
4041
/// <exception cref="ArgumentOutOfRangeException">当线程安全模式不支持时抛出。</exception>
41-
public static ICoreLogWriter CreateCoreLogWriter(this LogWritingThreadMode threadMode) => threadMode switch
42+
public static ICoreLogWriter CreateCoreLogWriter(this LogWritingThreadMode threadMode, Action<string> logger) => threadMode switch
4243
{
43-
LogWritingThreadMode.NotThreadSafe => new NotThreadSafeLogWriter(),
44-
LogWritingThreadMode.Lock => new LockLogWriter(),
45-
LogWritingThreadMode.ProducerConsumer => new ProducerConsumerLogWriter(),
44+
LogWritingThreadMode.NotThreadSafe => new NotThreadSafeLogWriter(logger),
45+
LogWritingThreadMode.Lock => new LockLogWriter(logger),
46+
LogWritingThreadMode.ProducerConsumer => new ProducerConsumerLogWriter(logger),
4647
_ => throw new ArgumentOutOfRangeException(nameof(threadMode)),
4748
};
4849
}

0 commit comments

Comments
 (0)