From 22963a48c46abbfdf592acf4c5a110dfc3ba076e Mon Sep 17 00:00:00 2001 From: hadashiA Date: Thu, 19 Oct 2023 15:18:17 +0900 Subject: [PATCH] Add option to write the specified log level to standard error --- sandbox/ConsoleApp/Program.cs | 2 +- src/ZLogger/AsyncStreamLineMessageWriter.cs | 20 ++++++++++--------- .../SystemTextJsonZLoggerFormatter.cs | 1 - .../Providers/ZLoggerConsoleLoggerProvider.cs | 7 +++---- .../Providers/ZLoggerFileLoggerProvider.cs | 2 +- .../ZLoggerRollingFileLoggerProvider.cs | 2 +- .../Providers/ZLoggerStreamLoggerProvider.cs | 3 +-- .../ZLoggerLoggingBuilderExtensions.cs | 14 ++++++------- src/ZLogger/ZLoggerOptions.cs | 3 ++- 9 files changed, 26 insertions(+), 28 deletions(-) diff --git a/sandbox/ConsoleApp/Program.cs b/sandbox/ConsoleApp/Program.cs index d754b01d..ab3e1595 100644 --- a/sandbox/ConsoleApp/Program.cs +++ b/sandbox/ConsoleApp/Program.cs @@ -157,7 +157,6 @@ static async Task Main(string[] args) { Environment.SetEnvironmentVariable("DOTNET_ENVIRONMENT", "Development"); - var host = Host.CreateDefaultBuilder() .ConfigureServices(x => { @@ -174,6 +173,7 @@ static async Task Main(string[] args) { //options.FlushRate = TimeSpan.FromSeconds(5); + options.LogToErrorThreshold = LogLevel.Error; #if DEBUG options.UsePlainTextFormatter(plainText => { diff --git a/src/ZLogger/AsyncStreamLineMessageWriter.cs b/src/ZLogger/AsyncStreamLineMessageWriter.cs index 2da4d469..84f263ad 100644 --- a/src/ZLogger/AsyncStreamLineMessageWriter.cs +++ b/src/ZLogger/AsyncStreamLineMessageWriter.cs @@ -1,11 +1,7 @@ -using System; -using System.Diagnostics; -using System.IO; +using System.Diagnostics; using System.Runtime.CompilerServices; using System.Text; -using System.Threading; using System.Threading.Channels; -using System.Threading.Tasks; namespace ZLogger { @@ -17,12 +13,13 @@ public class AsyncStreamLineMessageWriter : IAsyncLogProcessor, IAsyncDisposable readonly byte newLine2; readonly Stream stream; + readonly Stream? errorStream; readonly Channel channel; readonly Task writeLoop; readonly ZLoggerOptions options; readonly CancellationTokenSource cancellationTokenSource; - public AsyncStreamLineMessageWriter(Stream stream, ZLoggerOptions options) + public AsyncStreamLineMessageWriter(Stream stream, Stream? errorStream, ZLoggerOptions options) { this.newLine = Encoding.UTF8.GetBytes(Environment.NewLine); this.cancellationTokenSource = new CancellationTokenSource(); @@ -43,6 +40,7 @@ public AsyncStreamLineMessageWriter(Stream stream, ZLoggerOptions options) this.options = options; this.stream = stream; + this.errorStream = errorStream; this.channel = Channel.CreateUnbounded(new UnboundedChannelOptions { AllowSynchronousContinuations = false, // always should be in async loop. @@ -86,6 +84,7 @@ void AppendLine(StreamBufferWriter writer) async Task WriteLoop() { var writer = new StreamBufferWriter(stream); + var errorWriter = errorStream != null ? new StreamBufferWriter(errorStream) : null; var formatter = options.CreateFormatter(); var reader = channel.Reader; var sw = Stopwatch.StartNew(); @@ -99,9 +98,11 @@ async Task WriteLoop() while (reader.TryRead(out var value)) { info = value.LogInfo; - value.FormatUtf8(writer, formatter); - (value as IReturnableZLoggerEntry)?.Return(); - AppendLine(writer); + var currentWriter = errorWriter != null && info.LogLevel >= options.LogToErrorThreshold + ? errorWriter + : writer; + value.FormatUtf8(currentWriter, formatter); + AppendLine(currentWriter); } info = default; @@ -166,6 +167,7 @@ public async ValueTask DisposeAsync() finally { this.stream.Dispose(); + this.errorStream?.Dispose(); } } } diff --git a/src/ZLogger/Formatters/SystemTextJsonZLoggerFormatter.cs b/src/ZLogger/Formatters/SystemTextJsonZLoggerFormatter.cs index 8f37e9da..f30799d9 100644 --- a/src/ZLogger/Formatters/SystemTextJsonZLoggerFormatter.cs +++ b/src/ZLogger/Formatters/SystemTextJsonZLoggerFormatter.cs @@ -1,4 +1,3 @@ -using System; using System.Buffers; using System.Text.Encodings.Web; using System.Text.Json; diff --git a/src/ZLogger/Providers/ZLoggerConsoleLoggerProvider.cs b/src/ZLogger/Providers/ZLoggerConsoleLoggerProvider.cs index 48987c7b..b05f1cbb 100644 --- a/src/ZLogger/Providers/ZLoggerConsoleLoggerProvider.cs +++ b/src/ZLogger/Providers/ZLoggerConsoleLoggerProvider.cs @@ -20,11 +20,11 @@ public ZLoggerConsoleLoggerProvider(IOptionsMonitor options) } public ZLoggerConsoleLoggerProvider(bool consoleOutputEncodingToUtf8, string? optionName, IOptionsMonitor options) - : this(consoleOutputEncodingToUtf8, false, optionName, options) + : this(consoleOutputEncodingToUtf8, LogLevel.None, optionName, options) { } - public ZLoggerConsoleLoggerProvider(bool consoleOutputEncodingToUtf8, bool outputToErrorStream, string? optionName, IOptionsMonitor options) + public ZLoggerConsoleLoggerProvider(bool consoleOutputEncodingToUtf8, LogLevel logToStandardErrorThreshold, string? optionName, IOptionsMonitor options) { if (consoleOutputEncodingToUtf8) { @@ -32,8 +32,7 @@ public ZLoggerConsoleLoggerProvider(bool consoleOutputEncodingToUtf8, bool outpu } this.options = options.Get(optionName ?? DefaultOptionName); - var stream = outputToErrorStream ? Console.OpenStandardError() : Console.OpenStandardOutput(); - this.streamWriter = new AsyncStreamLineMessageWriter(stream, this.options); + this.streamWriter = new AsyncStreamLineMessageWriter(Console.OpenStandardOutput(), Console.OpenStandardError(), this.options); } public ILogger CreateLogger(string categoryName) diff --git a/src/ZLogger/Providers/ZLoggerFileLoggerProvider.cs b/src/ZLogger/Providers/ZLoggerFileLoggerProvider.cs index 6efd1025..90367629 100644 --- a/src/ZLogger/Providers/ZLoggerFileLoggerProvider.cs +++ b/src/ZLogger/Providers/ZLoggerFileLoggerProvider.cs @@ -30,7 +30,7 @@ public ZLoggerFileLoggerProvider(string filePath, string? optionName, IOptionsMo // useAsync:false, use sync(in thread) processor, don't use FileStream buffer(use buffer size = 1). var stream = new FileStream(filePath, FileMode.Append, FileAccess.Write, FileShare.ReadWrite, 1, false); - this.streamWriter = new AsyncStreamLineMessageWriter(stream, this.options); + this.streamWriter = new AsyncStreamLineMessageWriter(stream, null, this.options); } public ILogger CreateLogger(string categoryName) diff --git a/src/ZLogger/Providers/ZLoggerRollingFileLoggerProvider.cs b/src/ZLogger/Providers/ZLoggerRollingFileLoggerProvider.cs index 54dc50ef..50441516 100644 --- a/src/ZLogger/Providers/ZLoggerRollingFileLoggerProvider.cs +++ b/src/ZLogger/Providers/ZLoggerRollingFileLoggerProvider.cs @@ -22,7 +22,7 @@ public ZLoggerRollingFileLoggerProvider(Func fileNa { this.options = options.Get(optionName ?? DefaultOptionName); var stream = new RollingFileStream(fileNameSelector, timestampPattern, rollSizeKB, this.options); - this.streamWriter = new AsyncStreamLineMessageWriter(stream, this.options); + this.streamWriter = new AsyncStreamLineMessageWriter(stream, null, this.options); } public ILogger CreateLogger(string categoryName) diff --git a/src/ZLogger/Providers/ZLoggerStreamLoggerProvider.cs b/src/ZLogger/Providers/ZLoggerStreamLoggerProvider.cs index a33a58fb..a277fdd1 100644 --- a/src/ZLogger/Providers/ZLoggerStreamLoggerProvider.cs +++ b/src/ZLogger/Providers/ZLoggerStreamLoggerProvider.cs @@ -1,6 +1,5 @@ using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; -using System.IO; namespace ZLogger.Providers { @@ -21,7 +20,7 @@ public ZLoggerStreamLoggerProvider(Stream stream, IOptionsMonitor options) { this.options = options.Get(optionName ?? DefaultOptionName); - this.streamWriter = new AsyncStreamLineMessageWriter(stream, this.options); + this.streamWriter = new AsyncStreamLineMessageWriter(stream, null, this.options); } public ILogger CreateLogger(string categoryName) diff --git a/src/ZLogger/ZLoggerLoggingBuilderExtensions.cs b/src/ZLogger/ZLoggerLoggingBuilderExtensions.cs index ef7f8052..1a4f5890 100644 --- a/src/ZLogger/ZLoggerLoggingBuilderExtensions.cs +++ b/src/ZLogger/ZLoggerLoggingBuilderExtensions.cs @@ -2,8 +2,6 @@ using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Configuration; using Microsoft.Extensions.Options; -using System; -using System.IO; using System.Runtime.InteropServices; using ZLogger.Providers; @@ -11,7 +9,7 @@ namespace ZLogger { public static class ZLoggerLoggingBuilderExtensions { - public static ILoggingBuilder AddZLoggerConsole(this ILoggingBuilder builder, bool consoleOutputEncodingToUtf8 = true, bool configureEnableAnsiEscapeCode = false, bool outputToErrorStream = false) + public static ILoggingBuilder AddZLoggerConsole(this ILoggingBuilder builder, bool consoleOutputEncodingToUtf8 = true, bool configureEnableAnsiEscapeCode = false) { if (configureEnableAnsiEscapeCode) { @@ -19,18 +17,18 @@ public static ILoggingBuilder AddZLoggerConsole(this ILoggingBuilder builder, bo } builder.AddConfiguration(); - builder.Services.Add(ServiceDescriptor.Singleton(x => new ZLoggerConsoleLoggerProvider(consoleOutputEncodingToUtf8, outputToErrorStream, null, x.GetRequiredService>()))); + builder.Services.Add(ServiceDescriptor.Singleton(x => new ZLoggerConsoleLoggerProvider(consoleOutputEncodingToUtf8, null, x.GetRequiredService>()))); LoggerProviderOptions.RegisterProviderOptions(builder.Services); return builder; } - public static ILoggingBuilder AddZLoggerConsole(this ILoggingBuilder builder, Action configure, bool consoleOutputEncodingToUtf8 = true, bool configureEnableAnsiEscapeCode = false, bool outputToErrorStream = false) + public static ILoggingBuilder AddZLoggerConsole(this ILoggingBuilder builder, Action configure, bool consoleOutputEncodingToUtf8 = true, bool configureEnableAnsiEscapeCode = false) { - return AddZLoggerConsole(builder, ZLoggerConsoleLoggerProvider.DefaultOptionName, configure, consoleOutputEncodingToUtf8: consoleOutputEncodingToUtf8, configureEnableAnsiEscapeCode: configureEnableAnsiEscapeCode, outputToErrorStream: outputToErrorStream); + return AddZLoggerConsole(builder, ZLoggerConsoleLoggerProvider.DefaultOptionName, configure, consoleOutputEncodingToUtf8: consoleOutputEncodingToUtf8, configureEnableAnsiEscapeCode: configureEnableAnsiEscapeCode); } - public static ILoggingBuilder AddZLoggerConsole(this ILoggingBuilder builder, string optionName, Action configure, bool consoleOutputEncodingToUtf8 = true, bool configureEnableAnsiEscapeCode = false, bool outputToErrorStream = false) + public static ILoggingBuilder AddZLoggerConsole(this ILoggingBuilder builder, string optionName, Action configure, bool consoleOutputEncodingToUtf8 = true, bool configureEnableAnsiEscapeCode = false) { if (configureEnableAnsiEscapeCode) { @@ -43,7 +41,7 @@ public static ILoggingBuilder AddZLoggerConsole(this ILoggingBuilder builder, st } builder.AddConfiguration(); - builder.Services.Add(ServiceDescriptor.Singleton(x => new ZLoggerConsoleLoggerProvider(consoleOutputEncodingToUtf8, outputToErrorStream, optionName, x.GetRequiredService>()))); + builder.Services.Add(ServiceDescriptor.Singleton(x => new ZLoggerConsoleLoggerProvider(consoleOutputEncodingToUtf8, optionName, x.GetRequiredService>()))); LoggerProviderOptions.RegisterProviderOptions(builder.Services); builder.Services.AddOptions(optionName).Configure(configure); diff --git a/src/ZLogger/ZLoggerOptions.cs b/src/ZLogger/ZLoggerOptions.cs index 5eb641c7..cd0240dd 100644 --- a/src/ZLogger/ZLoggerOptions.cs +++ b/src/ZLogger/ZLoggerOptions.cs @@ -1,4 +1,4 @@ -using System; +using Microsoft.Extensions.Logging; using ZLogger.Formatters; namespace ZLogger @@ -8,6 +8,7 @@ public class ZLoggerOptions public Action? InternalErrorLogger { get; set; } public TimeSpan? FlushRate { get; set; } public bool IncludeScopes { get; set; } + public LogLevel LogToErrorThreshold { get; set; } = LogLevel.None; Func formatterFactory = DefaultFormatterFactory;