簡體   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