Skip to content

Commit

Permalink
Merge pull request #189 from AlanLiu90/Branch_FixConsole
Browse files Browse the repository at this point in the history
Fix thread safe issue about console output
  • Loading branch information
neuecc authored Dec 5, 2024
2 parents 395235e + 3f0bfed commit fc06513
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 22 deletions.
16 changes: 1 addition & 15 deletions src/ZLogger/AsyncStreamLineMessageWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,8 @@ public sealed class AsyncStreamLineMessageWriter : IAsyncLogProcessor, IAsyncDis
readonly Channel<IZLoggerEntry> channel;
readonly Task writeLoop;
readonly ZLoggerOptions options;
readonly Func<LogLevel, bool>? levelFilter;

public AsyncStreamLineMessageWriter(Stream stream, ZLoggerOptions options)
: this(stream, options, null)
{
}

// handling `Func<LogLevel, bool>? levelFilter` correctly is very context dependent.
// so only allows internal provider.
internal AsyncStreamLineMessageWriter(Stream stream, ZLoggerOptions options, Func<LogLevel, bool>? levelFilter = null)
public AsyncStreamLineMessageWriter(Stream stream, ZLoggerOptions options)
{
this.newLine = Encoding.UTF8.GetBytes(Environment.NewLine);
if (newLine.Length == 1)
Expand All @@ -46,7 +38,6 @@ internal AsyncStreamLineMessageWriter(Stream stream, ZLoggerOptions options, Fun

this.options = options;
this.stream = stream;
this.levelFilter = levelFilter;

channel = this.options.FullMode switch
{
Expand Down Expand Up @@ -121,7 +112,6 @@ async Task WriteLoop()
var writer = new StreamBufferWriter(stream);
var formatter = options.CreateFormatter();
var withLineBreak = formatter.WithLineBreak;
var requireFilterCheck = levelFilter != null;
var reader = channel.Reader;

while (await reader.WaitToReadAsync().ConfigureAwait(false))
Expand All @@ -130,10 +120,6 @@ async Task WriteLoop()
{
while (reader.TryRead(out var value))
{
if (requireFilterCheck && levelFilter!.Invoke(value.LogInfo.LogLevel) == false)
{
continue;
}
try
{
value.FormatUtf8(writer, formatter);
Expand Down
19 changes: 12 additions & 7 deletions src/ZLogger/Providers/ZLoggerConsoleLoggerProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,9 @@ public ZLoggerConsoleLoggerProvider(ZLoggerConsoleOptions options)
{
var logToStandardErrorThreshold = options.LogToStandardErrorThreshold;
processor = new DualAsyncLogProcessor(
new AsyncStreamLineMessageWriter(Console.OpenStandardOutput(), this.options, level => level < logToStandardErrorThreshold),
new AsyncStreamLineMessageWriter(Console.OpenStandardError(), this.options, level => level >= logToStandardErrorThreshold));
new AsyncStreamLineMessageWriter(Console.OpenStandardOutput(), this.options),
new AsyncStreamLineMessageWriter(Console.OpenStandardError(), this.options),
level => level < logToStandardErrorThreshold);
}
}

Expand All @@ -52,14 +53,18 @@ public void SetScopeProvider(IExternalScopeProvider scopeProvider)
this.scopeProvider = scopeProvider;
}

sealed class DualAsyncLogProcessor(AsyncStreamLineMessageWriter processor1, AsyncStreamLineMessageWriter processor2) : IAsyncLogProcessor
sealed class DualAsyncLogProcessor(AsyncStreamLineMessageWriter processor1, AsyncStreamLineMessageWriter processor2, Func<LogLevel, bool> levelFilter) : IAsyncLogProcessor
{
public void Post(IZLoggerEntry log)
{
// Post two entry is dangerous for log-state reference count cache.
// However filtered reader-loop does not call Return so ok to post multiple.
processor1.Post(log);
processor2.Post(log);
if (levelFilter(log.LogInfo.LogLevel))
{
processor1.Post(log);
}
else
{
processor2.Post(log);
}
}

public async ValueTask DisposeAsync()
Expand Down

0 comments on commit fc06513

Please sign in to comment.