如何通过JSON配置覆盖Serilog代码中日志记录器的级别?
原始问题
我编写了以下代码:
return Host.CreateDefaultBuilder() .UseSerilog((context, services, configuration) => configuration .MinimumLevel.Verbose() .ReadFrom.Configuration(_configuration) .ReadFrom.Services(services) .Enrich.FromLogContext() .Enrich.With(UserLoginEnricher.GetInstance()) .Enrich.With(new LoggersAdditionalEnricher()) //CSV logger .WriteTo.Logger(x => { x.WriteTo.File(ApplicationConfiguration.FullPathToCsvFile, rollingInterval: RollingInterval.Day, encoding: Encoding.Unicode, retainedFileCountLimit: ApplicationConfiguration.AppSettingsOptions.RetainDataCount, outputTemplate: "{Message}{NewLine}"); //log filter x.Filter.ByIncludingOnly(e => { if (!e.Properties.ContainsKey(nameof(LogType))) return false; return e.Properties[nameof(LogType)].ToString() == LogType.CSV.ToString(); }); }) .WriteTo(x =>{...}) .WriteTo(x =>{...});
是否可以通过Serilog的JSON配置修改File日志记录器的最低级别,且无需修改代码?
我的Serilog JSON配置如下:
"Serilog": { "Using": [ "Serilog.Sinks.File" ], "MinimumLevel": { "Default": "Verbose", "Override": { "Microsoft": "Warning", "Microsoft.EntityFrameworkCore.Database.Command": "Warning" } } }
需求是:多个日志记录器中,所有日志记录器以Warning级别写入,仅CSV日志记录器以Information级别写入。
更新补充
我在代码中写了多个写入文件的WriteTo日志记录器,希望不修改代码的前提下,让其中一个(CSV那个)用Information级别,其他用Warning级别。
我猜测因为文件名是动态生成的(示例:[_RU-PF10PUV1_][_Vlad.Pupkin_][_CalendarCollector_OutlookCalendarLog_][_20220921.csv),所以没法通过JSON配置重写这些日志记录器,这个猜测对吗?
另外我想知道能不能通过JSON配置覆盖现有代码配置,比如:
"Override": { "Utility.Logging.LogType.CSV": "Information"// LogType.CSV是日志消息的属性 }
有没有解决办法?
1. 关于动态文件名的猜测正确
Serilog的JSON配置只能通过固定标识(如sink类型、命名空间)或预设过滤规则匹配日志记录器,你的文件名是动态生成的,JSON无法识别这种动态路径的sink,确实没法直接定位到CSV日志记录器单独修改级别。
2. 针对日志属性的Override配置无效
你尝试的"Utility.Logging.LogType.CSV": "Information"不生效,因为Serilog的MinimumLevel.Override仅支持按命名空间/类型名称设置级别,不支持直接通过日志属性过滤配置。
3. 无需改代码的可行方案
方案一:用过滤器扩展实现级别区分
需要引入Serilog.Filters.Expressions包,然后修改JSON配置:
"Serilog": { "Using": [ "Serilog.Sinks.File", "Serilog.Filters.Expressions" ], "MinimumLevel": { "Default": "Warning", "Override": { "Microsoft": "Warning", "Microsoft.EntityFrameworkCore.Database.Command": "Warning" } }, "Filter": [ { "Name": "ByIncludingOnly", "Args": { "expression": "LogType = 'CSV'" } }, { "Name": "WithMinimumLevel", "Args": { "level": "Information" } } ] }
配置逻辑:全局默认Warning级别,所有LogType为CSV的日志会被过滤器单独提升到Information级别,刚好匹配你代码中CSV日志器的过滤规则,实现CSV日志器记录Information级内容,其他日志器仅记录Warning及以上。
方案二:极小代码改动+JSON配置(可选)
如果可以接受一行代码修改,可在CSV日志器的WriteTo.File中增加读取配置的参数:
x.WriteTo.File( ApplicationConfiguration.FullPathToCsvFile, rollingInterval: RollingInterval.Day, encoding: Encoding.Unicode, retainedFileCountLimit: ApplicationConfiguration.AppSettingsOptions.RetainDataCount, outputTemplate: "{Message}{NewLine}", restrictedToMinimumLevel: _configuration.GetValue<LogEventLevel>("Serilog:Sinks:CSV:MinimumLevel", LogEventLevel.Information) );
然后在JSON中新增配置节点:
"Serilog": { // 原有配置... "Sinks": { "CSV": { "MinimumLevel": "Information" } } }
后续可直接通过JSON调整级别,无需再改代码。
总结
完全不想改代码的话,优先选方案一;能接受极小代码改动的话,方案二更直接。
内容的提问来源于stack exchange,提问作者Владимир

