繁体   English   中英

为什么 DictionaryValue 在 ASP.NET Core 中的 Serilog 中转换为 ScalarValue

[英]Why the DictionaryValue is converted to ScalarValue in Serilog in ASP.NET Core

我的 Serilog 配置如下:

    LevelSwitch.MinimumLevel = LogEventLevel.Verbose;

    var loggerConfiguration =
        new LoggerConfiguration()
            .MinimumLevel.ControlledBy(LevelSwitch)
            .Enrich.FromLogContext()
            .WriteTo.Conditional(
                IsDictionaryValue,
                cfg => cfg.Console());

    services.AddLogging(configure => configure.AddSerilog());

其中IsDictionaryValue定义为:

    static bool IsDictionaryValue(LogEvent logEvent)
    {
        if (logEvent.Properties.TryGetValue("LOG_TEST", out LogEventPropertyValue value))
        {
            return value is DictionaryValue;
        }

        return false;
    }

尝试记录跟踪和信息消息:

    var logger = loggerFactory.CreateLogger<Program>();

    var dict = new Dictionary<string, object>
    {
        { "val1", 1 },
        { "val2", 2 },
        { "val3", "_3" },
    };

    logger.LogTrace("{@LOG_TEST}", dict);

    logger.LogInformation("{@LOG_TEST}", dict);

问题是:
为什么在 ASP.NET Core web 应用程序中,日志跟踪消息正确创建DictionaryValue并且IsDictionaryValue的结果为true ,但是当我记录信息消息时, LogEventPropertyValue值为ScalarValue


此“错误”仅存在于 ASP.NET Core web 应用程序中。 当我在控制台应用程序中使用相同的 Serilog 配置时,LogTrace 和 LogInformation 都正确地将dict字典表示为DictionaryValue

更新:
DictionaryValueLogEventPropertyValue的类型

日志方法 控制台应用 Web 应用程序
日志跟踪 字典值 字典值
日志调试 字典值 字典值
日志信息 字典值 标量值
日志警告 字典值 标量值
日志错误 字典值 标量值
逻辑临界 字典值 标量值

问题:
在 ASP.NET Core 中注册了一些默认LoggerProviders ,例如:

1. Microsoft.Extensions.Logging.Console.ConsoleLogger
2. Microsoft.Extensions.Logging.Debug.DebugLogger
3. Microsoft.Extensions.Logging.EventSource.EventSourceLogger
4. Microsoft.Extensions.Logging.EventLog.EventLogLogger

当你配置 serilog

services.AddLogging(configure => configure.AddSerilog());

添加了第五个LoggerProvider

5. Serilog.Extensions.Logging.SerilogLogger

其他提供者的默认配置是LogLevel:Information 这就是LogTraceLogDebug在 Web 应用程序中工作的原因。 因此,如果您调用LogInformation ,前四个记录器提供程序会命中TState

namespace Microsoft.Extensions.Logging
{
    internal class Logger : ILogger
    {
        public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
    }
}

并将原始dictionary转换为string 当第五个记录器提供程序(出SerilogLogger )开始播放时,它无法解析DictionaryValue因为TStatestring

解决方案:
SerilogLogger设置为第一个LoggerProvider

    public class Program
    {
        public static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                })
            .ConfigureLogging(cfg => cfg
                .ClearProviders()
                .AddSerilog()
                .AddConsole()
                .AddDebug()
                .AddEventSourceLogger()
                .AddEventLog());
    }

并且因为SerilogLoggerProvider是在IHostBuilderProgram.cs中注册的,所以在services.AddLogging(configure => configure.AddSerilog());中的AddSerilog() 没有必要。

services.AddLogging();

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM