如何使用 appsettings.json 覆盖 serilog 设置

我有一个扩展方法来配置我的记录器:


 public static class Extensions

 {

     public static IWebHostBuilder UseLogging(this IWebHostBuilder webHostBuilder) =>

         webHostBuilder.UseSerilog((context, loggerConfiguration) =>

         {

             var logLevel = context.Configuration.GetValue<string>("Serilog:MinimumLevel");

             if (!Enum.TryParse<LogEventLevel>(logLevel, true, out var level))

             {

                 level = LogEventLevel.Information;

             }


             loggerConfiguration.Enrich

                 .FromLogContext()

                 .MinimumLevel.Is(level);


             loggerConfiguration

                 .ReadFrom.Configuration(context.Configuration)

                 .WriteTo.Console(

                     theme: AnsiConsoleTheme.Code,

                     outputTemplate: "[{Timestamp:yy-MM-dd HH:mm:ss} {Level:u3}] {Message:lj} <s:{SourceContext}>{NewLine}{Exception}");

         });

 }

我添加了这一行.ReadFrom.Configuration(context.Configuration)并期望来自 appsettings.json 的所有设置都将覆盖当前配置。我的意思是,如果我在 appsettings.json 中指定其他 outputTemplate,那么它将覆盖现有的。


    "Serilog": {

        "WriteTo": [

            {

                "Name": "Console",

                "Args": {

                    "outputTemplate": "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj} <s:{SourceContext}>{NewLine}{Exception}"

                }

            }

        ]

    }

但它不起作用。现在日志消息是重复的,一个是代码格式的,另一个是配置格式的。如何在运行时覆盖 appsettings.json 中的一些设置?


[03:59:09 INF] 事件处理器服务正在启动。


[19-04-19 00:59:09 INF] 事件处理器服务正在启动。


我有在服务中使用的扩展方法,但有时我需要覆盖 appsettings.json(或环境变量)中的某些设置,我该怎么做?因为当前的解决方案不起作用并添加了第二个记录器


www说
浏览 211回答 1
1回答

慕尼黑5688855

您基本上必须检查配置是否已经指定了控制台记录器。存储接收器的字段是私有的。所以你必须使用类似的东西来对配置做出反应。当您想要覆盖记录器上的某些属性时,您还需要使用反射来访问这些字段。下面的代码适用于我的简单测试应用程序。&nbsp; &nbsp; public static class Extensions&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; public static IWebHostBuilder UseLogging(this IWebHostBuilder webHostBuilder) =>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; webHostBuilder.UseSerilog((context, loggerConfiguration) =>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var logLevel = context.Configuration.GetValue<string>("Serilog:MinimumLevel");&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (!Enum.TryParse<LogEventLevel>(logLevel, true, out var level))&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; level = LogEventLevel.Information;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; loggerConfiguration.Enrich&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .FromLogContext()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .MinimumLevel.Is(level);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; loggerConfiguration&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .ReadFrom.Configuration(context.Configuration);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Get the field that holds the sinks.&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var sinks = loggerConfiguration.GetType()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .GetField("_logEventSinks", BindingFlags.Instance | BindingFlags.NonPublic)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .GetValue(loggerConfiguration) as List<ILogEventSink>;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Get the sink type for reusage.&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var sinkType = typeof(AnsiConsoleTheme).Assembly.GetType("Serilog.Sinks.SystemConsole.ConsoleSink");&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Find the first sink of the right type.&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var sink = sinks?.FirstOrDefault(s => sinkType == s.GetType());&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Check if a sink was found.&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (sink == null)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // No sink found add a new one.&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; loggerConfiguration&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .WriteTo.Console(&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; theme: AnsiConsoleTheme.Code,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; outputTemplate:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "[{Timestamp:yy-MM-dd HH:mm:ss} {Level:u3}] {Message:lj} <s:{SourceContext}>{NewLine}{Exception}");&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; else&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Otherwise change the theme.&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sinkType.GetField("_theme", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(sink, AnsiConsoleTheme.Code);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; });&nbsp; &nbsp; }
打开App,查看更多内容
随时随地看视频慕课网APP