Appsettings.json中Serilog过滤规则不生效问题咨询
Serilog-Expressions 过滤健康检查日志的正确配置方案
一、核心排查:过滤规则的正确写法
过滤不生效大多是表达式错误或规则位置不对,先从最基础的配置入手:
1. 排除健康检查日志的两种常用方式
首先确保已安装Serilog.Expressions和Serilog.AspNetCore包,然后根据健康检查日志的特征配置过滤:
方式1:通过SourceContext排除
健康检查日志的SourceContext固定为Microsoft.AspNetCore.Diagnostics.HealthChecks,直接针对这个属性过滤最可靠:
"Serilog": { "Using": ["Serilog.Sinks.MSSqlServer", "Serilog.Expressions"], "MinimumLevel": "Information", "Filter": [ { "Name": "ByExcluding", "Args": { "expression": "SourceContext = 'Microsoft.AspNetCore.Diagnostics.HealthChecks'" } } ], "WriteTo": [ { "Name": "MSSqlServer", "Args": { "connectionString": "你的数据库连接字符串", "tableName": "Logs", "autoCreateSqlTable": true, "columnOptionsSection": { "addStandardColumns": ["RequestPath"] } } } ] }
方式2:通过RequestPath排除
如果想用RequestPath过滤但没效果,先确认已启用请求日志属性收集:
在Program.cs中添加:
builder.Host.UseSerilog((ctx, lc) => lc .ReadFrom.Configuration(ctx.Configuration) .Enrich.FromLogContext()); // 必须放在UseRouting之后 app.UseSerilogRequestLogging();
然后配置文件的过滤表达式改为:
"Filter": [ { "Name": "ByExcluding", "Args": { "expression": "RequestPath like '%health%'" } } ]
二、过滤规则的位置与优先级
- 全局过滤:写在
Serilog.Filter节点下,对所有Sink生效,这是最常用的方式。 - Sink级过滤:如果只想让MSSqlServer排除健康日志,其他Sink正常输出,用
Filtered包装Sink:
"WriteTo": [ { "Name": "Filtered", "Args": { "expression": "not (RequestPath like '%health%' or SourceContext = 'Microsoft.AspNetCore.Diagnostics.HealthChecks')", "writeTo": [ { "Name": "MSSqlServer", "Args": { // 你的SQL Sink配置 } } ] } } ]
三、过滤可用属性的来源
过滤表达式用的是日志事件的属性,不是数据库表的列名,属性来源分三类:
- 内置属性:Serilog自带的
SourceContext、Timestamp、Level、MessageTemplate等,所有日志事件都包含。 - 框架注入属性:ASP.NET Core提供的
RequestPath、RequestMethod、StatusCode等,需要通过UseSerilogRequestLogging()或Enrich.FromLogContext()收集,仅请求相关日志有这些属性。 - 自定义属性:自己通过
LogContext.PushProperty("CustomProp", value)添加的属性,或者日志语句中的变量(比如Log.Information("用户{UserId}操作", userId)里的UserId),均可用于过滤。
四、自定义列过滤无效的排查要点
如果自定义列(比如RequestPath)过滤没效果,检查这几点:
- 确认属性已注入日志事件:先把日志输出到控制台,查看日志的
Properties节点是否包含目标属性(比如RequestPath)。 - 属性名大小写严格匹配:日志事件中的属性名和过滤表达式里的要完全一致(比如
requestPath和RequestPath是两个不同属性)。 - 列名≠属性名:过滤基于日志事件的属性,数据库列名只是属性的存储映射,不能用列名写过滤表达式。
五、验证过滤生效的小技巧
- 先切换日志输出到控制台,看健康检查日志是否被过滤。如果控制台已过滤,说明是数据库Sink配置问题;如果控制台仍输出,是过滤表达式或属性收集的问题。
- 开启Serilog调试日志排查错误:在Program.cs中添加:
Serilog.Debugging.SelfLog.Enable(msg => Console.WriteLine(msg));
查看是否有属性找不到或表达式解析错误的提示。
内容的提问来源于stack exchange,提问作者Kaz
相关产品推荐
相关产品推荐

