C# Serilog使用子记录器与过滤器实现多文件输出的配置问题
C# Serilog 多格式日志分文件输出方案
需求背景
C#开发中使用Serilog组件时,需要实现两类日志分文件输出:
- 调用
WriteOperationalLog时输出常规格式日志 - 调用
WriteJsonLog时输出纯JSON格式日志
初始问题
最初尝试通过子记录器过滤JSON日志写入独立文件,但过滤器使用不当触发无限循环,初始配置代码如下:
Log.Logger = new LoggerConfiguration() .MinimumLevel.Debug() .WriteTo.File(filepath, rollingInterval: RollingInterval.Day) .WriteTo.Logger(lc => lc .Filter.ByIncludingOnly(WriteJsonLog) .WriteTo.File(new ExpressionTemplate("{ @m } \n"), filepathJson, rollingInterval: RollingInterval.Day)) .CreateLogger();
最终解决方案
步骤1:为JSON日志添加专属标记
在WriteJSONLog方法中通过Serilog.Context为JSON类日志添加专属属性标记,代码如下:
using(LogContext.PushProperty("JSON", true)) { Log.Information(json); }
步骤2:调整日志配置实现分流过滤
借助Serilog.Filters包的属性匹配规则,分别对两类日志做过滤,写入对应文件,修正后的配置如下:
Log.Logger = new LoggerConfiguration() .Enrich.FromLogContext() // 允许记录器读取日志上下文属性,此处用于识别JSON标识属性 .MinimumLevel.Debug() .WriteTo.Logger(lc => lc .Filter.ByExcluding(Matching.WithProperty("JSON")) // 排除带JSON标记的日志,剩余写入常规日志文件 .WriteTo.File(filepath, rollingInterval: RollingInterval.Day)) .WriteTo.Logger(lc => lc .Filter.ByIncludingOnly(Matching.WithProperty("JSON")) // 仅保留带JSON标记的日志,写入JSON专属文件 .WriteTo.File(new ExpressionTemplate("{ @m } \n"), filepathJson, rollingInterval: RollingInterval.Day)) // 仅输出原始JSON内容,无多余格式前缀后缀 .CreateLogger();
核心注意点
Enrich.FromLogContext()是必填配置,否则日志上下文添加的JSON属性不会被记录器识别,过滤器无法生效- 两个子记录器分别做互斥过滤,避免同一日志同时写入两个文件,也避免了过滤逻辑循环触发的问题
- 输出JSON文件时使用
ExpressionTemplate("{ @m } \n"),可以直接输出原始JSON字符串,不会额外添加Serilog默认的时间、级别等前缀,符合纯JSON日志的需求
内容的提问来源于stack exchange,提问作者EvilBurp
相关产品推荐
相关产品推荐

