.NET Framework 4.7下Serilog XML配置子记录器失效问题排查
.NET Framework 4.7下Serilog XML配置日志无文件输出问题
需求与现状
需要在.NET Framework 4.7环境中通过纯XML配置Serilog,实现:
- 常规日志写入
./Logs/logs.csv - 统计日志写入单独的
./Logs/statistics.csv - 代码中仅通过以下方式初始化日志:
Log.Logger = new LoggerConfiguration() .ReadFrom.AppSettings() .CreateLogger();
当前问题:配置后仅控制台有日志输出,文件日志完全无内容;但移除子记录器配置和主记录器的过滤表达式后,常规日志能正常写入文件。
现有配置与日志写入代码
XML配置(App.config)
<appSettings> <add key="serilog:using:File" value="Serilog.Sinks.File" /> <add key="serilog:using:Console" value="Serilog.Sinks.Console" /> <add key="serilog:using:Expressions" value="Serilog.Expressions" /> <add key="serilog:minimum-level" value="Information" /> <!-- MAIN SINK: Logs.csv --> <add key="serilog:write-to:File#main.name" value="File" /> <add key="serilog:write-to:File#main.path" value="./Logs/logs.csv" /> <add key="serilog:write-to:File#main.outputTemplate" value="{Timestamp:yyyy-MM-dd HH:mm:ss},{Level:u},{Message}{NewLine}" /> <add key="serilog:write-to:File#main.restrictedToMinimumLevel" value="Information" /> <add key="serilog:write-to:File#main.filter:ByExcluding.expression" value="IsStatistic = true" /> <!-- SUBLOGGER: Statistics log --> <add key="serilog:write-to:Logger.name" value="Logger" /> <add key="serilog:write-to:Logger.args.filter" value="IsStatistic = true" /> <add key="serilog:write-to:Logger.args.write-to:File.path" value="./Logs/statistics.csv" /> <add key="serilog:write-to:Logger.args.write-to:File.outputTemplate" value="{Timestamp:yyyy-MM-dd HH:mm:ss.fff},{Level:u},{Message}{NewLine}" /> <!-- Console sink --> <add key="serilog:write-to:Console.restrictedToMinimumLevel" value="Verbose" /> <add key="serilog:write-to:Console.outputTemplate" value="{Timestamp:HH:mm:ss} [{Level:u3}] {Message:lj}{NewLine}" /> </appSettings>
日志写入代码
- 常规日志:
Logger.Information(message, description);
- 统计日志:
Log.Logger.ForContext("IsStatistic", true).Information("{Action}, {Message}", action, message);
问题分析与修复方案
1. 配置格式错误
主记录器过滤配置错误
原配置中serilog:write-to:File#main.filter:ByExcluding.expression的格式不符合Serilog.Settings.AppSettings的要求,正确的过滤表达式配置应直接使用filter键,值为表达式字符串。
子记录器配置错误
子记录器的过滤配置键serilog:write-to:Logger.args.filter格式错误,且未给子记录器添加唯一标识(如#stats),容易导致配置解析失败。正确的子记录器过滤应直接使用filter键,无需嵌套args前缀。
2. 缺少必要的NuGet包
必须安装以下NuGet包:
Serilog:核心库Serilog.Sinks.File:文件输出接收器Serilog.Sinks.Console:控制台输出接收器Serilog.Expressions:支持表达式过滤(替代已弃用的Serilog.Filter.Expressions)Serilog.Settings.AppSettings:.NET Framework下读取AppSettings配置的核心依赖(极易遗漏)
修正后的XML配置
<appSettings> <add key="serilog:using:File" value="Serilog.Sinks.File" /> <add key="serilog:using:Console" value="Serilog.Sinks.Console" /> <add key="serilog:using:Expressions" value="Serilog.Expressions" /> <add key="serilog:minimum-level" value="Information" /> <!-- MAIN SINK: 常规日志,排除统计日志 --> <add key="serilog:write-to:File#main.path" value="./Logs/logs.csv" /> <add key="serilog:write-to:File#main.outputTemplate" value="{Timestamp:yyyy-MM-dd HH:mm:ss},{Level:u},{Message}{NewLine}" /> <add key="serilog:write-to:File#main.restrictedToMinimumLevel" value="Information" /> <add key="serilog:write-to:File#main.filter" value="!IsStatistic" /> <!-- SUBLOGGER: 统计日志,仅包含标记IsStatistic=true的日志 --> <add key="serilog:write-to:Logger#stats.filter" value="IsStatistic = true" /> <add key="serilog:write-to:Logger#stats.write-to:File.path" value="./Logs/statistics.csv" /> <add key="serilog:write-to:Logger#stats.write-to:File.outputTemplate" value="{Timestamp:yyyy-MM-dd HH:mm:ss.fff},{Level:u},{Message}{NewLine}" /> <!-- Console sink --> <add key="serilog:write-to:Console.restrictedToMinimumLevel" value="Verbose" /> <add key="serilog:write-to:Console.outputTemplate" value="{Timestamp:HH:mm:ss} [{Level:u3}] {Message:lj}{NewLine}" /> </appSettings>
修正说明
- 主记录器过滤改为
!IsStatistic表达式,直接通过filter键配置,替代原错误的filter:ByExcluding.expression格式。 - 子记录器添加
#stats唯一标识,过滤配置改为filter键,值为IsStatistic = true,确保配置被正确解析。 - 移除主记录器中多余的
name配置,File sink无需该参数。
内容的提问来源于stack exchange,提问作者Nickolodeon
相关产品推荐
相关产品推荐

