ASP.NET Core 8中Serilog对接Splunk时日志嵌套合并问题及仅保留自定义业务日志的实现方案咨询
我来帮你梳理下这个问题的解决方案,你遇到的两个核心问题分别是Splunk日志嵌套难读,以及框架自动生成的日志(比如HTTP请求日志)混入了你的业务日志里,咱们一步步来解决:
一、先搞定Splunk日志嵌套难读的问题
你现在看到Splunk里的日志是嵌套JSON,核心原因是Serilog的Splunk Sink默认会把整个日志事件打包成event字段传给Splunk,导致所有内容都嵌套在这个字段里。咱们可以通过指定输出模板或者格式化器把日志字段展平:
1. 用OutputTemplate直接展平日志
修改你Serilog配置中Splunk的WriteTo节点,添加outputTemplate参数,把你关心的字段直接输出,比如:
{ "Name": "EventCollector", "Args": { "splunkHost": "https:HOST.COM:8088", "eventCollectorToken": "tokenValue", "uriPath": "urlPath", "index": "index", "source": "APP NM", "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff} [{Level:u3}] {Username} {Message}{NewLine}{Exception}", "restrictedToMinimumLevel": "Information" } }
这样Splunk收到的就是你熟悉的格式化字符串,而不是嵌套的JSON结构,阅读起来就方便多了。
2. 用JSON格式化器生成扁平JSON(可选)
如果你还是想保留JSON格式但不想嵌套,可以指定JsonFormatter并开启渲染消息的选项,让Message直接展平:
{ "Name": "EventCollector", "Args": { // 其他参数不变 "formatter": "Serilog.Formatting.Json.JsonFormatter, Serilog", "formatterArgs": { "renderMessage": true, "compact": false } } }
这个配置会把渲染后的消息直接放在JSON的顶级字段里,避免嵌套在event中。
二、只保留你自己写的业务日志
你现在看到的HTTP GET / responded 401...这类日志,是app.UseSerilogRequestLogging();自动生成的请求日志,还有可能混入了Microsoft/System框架的日志。咱们有几种方案可以过滤掉这些非业务日志:
方案1:直接禁用自动请求日志
如果完全不需要HTTP请求日志,最简单的方法就是把Program.cs里的app.UseSerilogRequestLogging();这行代码删掉,这样框架就不会自动生成这类日志了。
方案2:通过日志级别过滤框架日志
如果你还需要保留部分框架的Warning级日志,但要去掉请求日志,可以在Serilog的MinimumLevel.Override里添加对Serilog请求日志组件的禁用:
"MinimumLevel": { "Default": "Information", "Override": { "Microsoft": "Warning", "System": "Warning", "Serilog.AspNetCore.RequestLoggingMiddleware": "None" } }
把Serilog.AspNetCore.RequestLoggingMiddleware的级别设为None,就会完全过滤掉它的所有日志输出。
方案3:只保留你项目命名空间下的日志
如果你想更精准地只保留自己代码里写的日志(比如你的项目根命名空间是GapsWeb),可以给Serilog添加过滤规则,只包含指定命名空间的日志:
"Serilog": { // 其他配置不变 "Filter": [ { "Name": "ByIncludingOnly", "Args": { "expression": "StartsWith(SourceContext, 'GapsWeb')" } } ] }
这个规则会只保留SourceContext以GapsWeb开头的日志(也就是你自己代码里_logger实例生成的日志),自动过滤掉Microsoft、System以及Serilog请求日志这类外来日志。
三、完整的修改后配置示例
结合上面的方案,给你一个完整的Serilog配置参考:
{ "Serilog": { "Using": [ "Serilog.Sinks.Console", "Serilog.Sinks.File", "Serilog.Sinks.Splunk" ], "MinimumLevel": { "Default": "Information", "Override": { "Microsoft": "Warning", "System": "Warning", "Serilog.AspNetCore.RequestLoggingMiddleware": "None" } }, "WriteTo": [ { "Name": "Console" }, { "Name": "File", "Args": { "path": "c:\\home\\LogFiles\\APP NM\\App-.log", "rollingInterval": "Day", "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff} {CorrelationId} [{Level:u3}] {Username} {Message}{NewLine:1}{Exception:1}" } }, { "Name": "File", "Args": { "path": "c:\\home\\LogFiles\\APP NM\\App-.json", "formatter": "Serilog.Formatting.Json.JsonFormatter, Serilog" } }, { "Name": "EventCollector", "Args": { "splunkHost": "https:HOST.COM:8088", "eventCollectorToken": "tokenValue", "uriPath": "urlPath", "index": "index", "source": "APP NM", "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff} {CorrelationId} [{Level:u3}] {Username} {Message}{NewLine}{Exception}", "restrictedToMinimumLevel": "Information" } } ], "Properties": { "ApplicationName": "GapsWeb" } } }
同时,如果你不需要请求日志,记得删掉Program.cs里的app.UseSerilogRequestLogging();。
最后验证
修改完配置后,重启应用,用_logger写几条业务日志,然后去Splunk里查看:
- 日志应该不再是嵌套的JSON,格式清晰易读
- 只会显示你自己写的业务日志,没有HTTP请求日志和框架日志的混入
内容来源于stack exchange

