Serilog按EventType属性过滤日志:JSON转代码遇阻求助
根据EventType属性将Serilog日志输出到不同Sink的硬编码实现方案
需求背景
需要根据日志事件的EventType属性值,把日志分发到不同的输出Sink。已经通过JSON配置搞定了这个策略,但在C#硬编码时踩了坑,试了Serilog Expressions的语法后完全没日志输出。
原JSON配置片段
之前能用的JSON配置大概是这样:
{ "Serilog": { "WriteTo": [ { "Name": "Conditional", "Args": { "condition": "EventType = 'Error'", "sink": { "Name": "File", "Args": { "path": "./logs/errors.log" } } } }, { "Name": "Conditional", "Args": { "condition": "EventType = 'Info'", "sink": { "Name": "File", "Args": { "path": "./logs/info.log" } } } } ] } }
尝试失败的C#代码
我一开始试了两种写法都没输出:
第一种直接硬写属性判断:
Log.Logger = new LoggerConfiguration() .WriteTo.File("./logs/errors.log", restrictedToMinimumLevel: LogEventLevel.Error, filter: e => e.Properties["EventType"].ToString() == "'Error'") .WriteTo.File("./logs/info.log", restrictedToMinimumLevel: LogEventLevel.Information, filter: e => e.Properties["EventType"].ToString() == "'Info'") .CreateLogger();
第二种尝试用Serilog Expressions的语法,结果也不行:
Log.Logger = new LoggerConfiguration() .WriteTo.File("./logs/errors.log", filter: "@EventType = 'Error'") .WriteTo.File("./logs/info.log", filter: "@EventType = 'Info'") .CreateLogger();
可行方案:用WriteTo.Conditional实现
后来改用WriteTo.Conditional就成功了,正确的硬编码写法如下:
Log.Logger = new LoggerConfiguration() .WriteTo.Conditional( condition: e => e.Properties.TryGetValue("EventType", out var eventType) && eventType.ToString() == "'Error'", sink: wt => wt.File("./logs/errors.log")) .WriteTo.Conditional( condition: e => e.Properties.TryGetValue("EventType", out var eventType) && eventType.ToString() == "'Info'", sink: wt => wt.File("./logs/info.log")) .CreateLogger();
提示:如果不想处理ToString()带单引号的问题,可以用更精准的类型判断来获取属性值:
.WriteTo.Conditional( condition: e => e.Properties.TryGetValue("EventType", out var eventType) && eventType is ScalarValue scalar && scalar.Value.ToString() == "Error", sink: wt => wt.File("./logs/errors.log"))
更推荐的方案:WriteTo.Logger
如果你的日志规则更复杂(比如不同Sink要设置不同的日志级别、格式化器),WriteTo.Logger嵌套配置的方式更合适,优势很明显:
- 每个子Logger可以独立配置完整的日志规则,包括级别过滤、格式化、输出Sink等
- 结构更清晰,后续维护复杂的多Sink策略更方便
示例代码:
Log.Logger = new LoggerConfiguration() .WriteTo.Logger(lc => lc .Filter.ByIncludingOnly(e => e.Properties.TryGetValue("EventType", out var et) && et is ScalarValue s && s.Value.ToString() == "Error") .WriteTo.File("./logs/errors.log", restrictedToMinimumLevel: LogEventLevel.Error)) .WriteTo.Logger(lc => lc .Filter.ByIncludingOnly(e => e.Properties.TryGetValue("EventType", out var et) && et is ScalarValue s && s.Value.ToString() == "Info") .WriteTo.File("./logs/info.log", restrictedToMinimumLevel: LogEventLevel.Information)) .CreateLogger();
内容的提问来源于stack exchange,提问作者Sirosimo
相关产品推荐
相关产品推荐

