【问题标题】:Is it possible to set a specific formatter for an ILoggerProvider wrapped by serilog?是否可以为由 serilog 包装的 ILoggerProvider 设置特定的格式化程序?
【发布时间】:2020-04-30 08:51:39
【问题描述】:

我已按照https://github.com/serilog/serilog-aspnetcore 的说明进行操作,并拥有以下代码:

public class Program
{
    static readonly LoggerProviderCollection Providers = new LoggerProviderCollection();

    public static int Main(string[] args)
    {
        Log.Logger = new LoggerConfiguration()
            .MinimumLevel.Debug()
            .MinimumLevel.Override("Microsoft", LogEventLevel.Information)
            .Enrich.FromLogContext()
            .WriteTo.Console(new CompactJsonFormatter())
            .WriteTo.Providers(Providers)
            .CreateLogger();

        try
        {
            Log.Information("Starting web host");
            CreateHostBuilder(args).Build().Run();
            return 0;
        }
        catch (Exception ex)
        {
            Log.Fatal(ex, "Host terminated unexpectedly");
            return 1;
        }
        finally
        {
            Log.CloseAndFlush();
        }
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureLogging(logging =>
            {
                logging.ClearProviders();
                logging.AddAzureWebAppDiagnostics();
            })
            .UseSerilog(providers: Providers)
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
}

logging.AddAzureWebAppDiagnostics() 使用BlobLoggerProvider 将日志记录配置到 azure blob 存储,serilog 能够使用此提供程序并写入 blob 存储。

我想将BlobLoggerProvider 的格式化程序更改为CompactJsonFormatter,但我不知道怎么做。是否可以为 serilog 包装的 ILoggerProvider 设置特定的格式化程序?

【问题讨论】:

    标签: asp.net-core serilog


    【解决方案1】:

    简短的回答是,这不可能为 serilog 包装的 ILoggerProvider 设置特定的格式化程序,也没有多大意义。

    Serilog 有一个接收器,它将日志调用转发到 Providers 集合中的每个 ILoggerProvider 实例。无法在此接收器中配置输出格式。

    class LoggerProviderCollectionSink : ILogEventSink, IDisposable
        {
            // ...
    
            public void Emit(LogEvent logEvent)
            {
                string categoryName = null;
    
                if (logEvent.Properties.TryGetValue("SourceContext", out var sourceContextProperty) &&
                    sourceContextProperty is ScalarValue sourceContextValue &&
                    sourceContextValue.Value is string sourceContext)
                {
                    categoryName = sourceContext;
                }
    
                var level = LevelConvert.ToExtensionsLevel(logEvent.Level);
                var slv = new SerilogLogValues(logEvent.MessageTemplate, logEvent.Properties);
    
                foreach (var provider in _providers.Providers)
                {
                    var logger = provider.CreateLogger(categoryName);
    
                    logger.Log(
                        level,
                        default, 
                        slv,
                        logEvent.Exception,
                        (s, e) => s.ToString());
                }
            }
            // ...      
        }
    

    LoggerProviderCollectionSink.cs

    ILoggerProvider 实现BlobLoggerProvider 继承自BatchingLoggerProviderBlobLoggerProvider 创建的记录器是BatchingLogger。此记录器在将日志消息写入队列之前对其进行自己的格式化,因此如果 serilog 向记录器提供 json 字符串,它不会有太大帮助。

    internal class BatchingLogger : ILogger
        {
            // ... 
    
            public void Log<TState>(DateTimeOffset timestamp, LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
            {
                if (!IsEnabled(logLevel))
                {
                    return;
                }
    
                var builder = new StringBuilder();
                builder.Append(timestamp.ToString("yyyy-MM-dd HH:mm:ss.fff zzz"));
                builder.Append(" [");
                builder.Append(logLevel.ToString());
                builder.Append("] ");
                builder.Append(_category);
    
                var scopeProvider = _provider.ScopeProvider;
                if (scopeProvider != null)
                {
                    scopeProvider.ForEachScope((scope, stringBuilder) =>
                    {
                        stringBuilder.Append(" => ").Append(scope);
                    }, builder);
    
                    builder.AppendLine(":");
                }
                else
                {
                    builder.Append(": ");
                }
    
                builder.AppendLine(formatter(state, exception));
    
                if (exception != null)
                {
                    builder.AppendLine(exception.ToString());
                }
    
                _provider.AddMessage(timestamp, builder.ToString());
            }
            // ...
        }
    

    BatchingLogger

    【讨论】:

      猜你喜欢
      • 2012-08-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-25
      • 2019-08-23
      • 1970-01-01
      • 2023-03-12
      • 2016-04-13
      • 2014-09-14
      相关资源
      最近更新 更多