如何在Serilog中过滤RequestLogging日志至独立Sink?
嗨,我来帮你搞定Serilog里请求日志和错误日志分流的问题!
首先得说,你之前用Level == LogEventLevel.Debug来过滤请求日志,大概率是行不通的——因为Serilog.AspNetCore的RequestLogging中间件默认生成的是Information级别的日志,除非你特意改了它的级别配置。所以按级别过滤不仅不准确,还会漏掉本该捕获的请求日志。
要精准筛选出所有RequestLogging事件,有两个更可靠的方法:
方法1:通过SourceContext属性过滤
Serilog的RequestLogging中间件生成的日志事件,自带一个SourceContext属性,值固定为Serilog.AspNetCore.RequestLoggingMiddleware。我们可以直接过滤这个属性:
.Filter.ByIncludingOnly(e => e.Properties.TryGetValue("SourceContext", out var sourceContext) && sourceContext.ToString().Equals("\"Serilog.AspNetCore.RequestLoggingMiddleware\"") )
这种方法不需要额外配置,直接利用中间件自带的属性,就能准确捕获所有请求日志,不受日志级别变化的影响。
方法2:自定义标记属性(更灵活)
如果你想让日志分类更清晰,或者以后要扩展其他日志类型,可以在配置RequestLogging时,给所有请求日志添加一个自定义属性,比如LogType: "Request":
首先在Startup/Program.cs里配置RequestLogging:
app.UseSerilogRequestLogging(options => { options.EnrichDiagnosticContext = (diagnosticContext, httpContext) => { // 添加自定义标记属性 diagnosticContext.Set("LogType", "Request"); }; });
然后过滤时就可以直接检查这个属性:
.Filter.ByIncludingOnly(e => e.Properties.TryGetValue("LogType", out var logType) && logType.ToString().Equals("\"Request\"") )
这种方式扩展性更强,比如后续要加业务日志,也可以给它们加LogType: "Business",过滤逻辑会非常统一。
最后提醒一下:分流的时候,错误日志可以用Filter.ByIncludingOnly(e => e.Level >= LogEventLevel.Error)来筛选,这样就能和请求日志完全分开,各自输出到不同的Sink啦!
内容的提问来源于stack exchange,提问作者José Fernández Alameda

