serilog需在webapplication.createbuilder前初始化log.logger,否则被内置日志抢占;appsettings.json需通过serilog.settings.configuration显式加载serilog节点;多输出须按级别过滤,控制台限warning以上,文件保留全量;useserilogrequestlogging自动注入请求属性,全局上下文用logcontext.pushproperty,避免高频forcontext创建。

Serilog 默认就支持结构化日志,Log.Information("User {Id} logged in", userId) 中的 {Id} 会被自动提取为 JSON 字段,不用额外配 layout 或 parser——这点和 NLog 有本质区别,别被“看起来能输出”骗了。
怎么在 Program.cs 里正确初始化 Serilog
必须在 Host.CreateDefaultBuilder 之前调用 Log.Logger = new LoggerConfiguration()...,否则 ASP.NET Core 的内置日志提供程序会先占位,导致 Serilog 不生效。
常见错误现象:ILogger<t></t> 注入的是 Microsoft 内置 logger,不是 Serilog 实例,LogContext.PushProperty 也无效。
实操建议:
- 把
Log.Logger = ...CreateLogger()放在var builder = WebApplication.CreateBuilder(args);之前 - 记得在应用退出前调用
Log.CloseAndFlush()(尤其控制台/Worker 项目) - 若用
Microsoft.Extensions.Logging的ILogger<t></t>,Serilog 会自动接管,无需手动注册
为什么 appsettings.json 配置不生效
Serilog.Settings.Configuration 包不是开箱即用的“自动加载”,它只读取 "Serilog" 节点,且要求你显式调用 .ReadFrom.Configuration(IConfiguration)。
常见错误现象:改了 appsettings.json 里的 MinimumLevel,日志级别没变;或 WriteTo.File 路径没更新。
实操建议:
- 安装
Serilog.Settings.ConfigurationNuGet 包 - 在
LoggerConfiguration中加.ReadFrom.Configuration(builder.Configuration) -
appsettings.json必须包含完整"Serilog"节点,例如:{ "Serilog": { "MinimumLevel": "Information", "WriteTo": [ { "Name": "Console" }, { "Name": "File", "Args": { "path": "logs/app-.txt", "rollingInterval": "Day" } } ] } }
多目标输出时 Debug 日志只该进文件,不该刷屏控制台
默认所有 WriteTo 都接收全量日志,不设限就会让控制台塞满 Debug,而文件里又漏掉关键上下文。
实操建议:
- 控制台加过滤:
.WriteTo.Console(restrictedToMinimumLevel: LogEventLevel.Warning) - 文件保留全量:
.WriteTo.File("logs/app-.txt", rollingInterval: RollingInterval.Day, retainedFileCountLimit: 30) - Seq 等远程 sink 必须启用结构化传输:
.WriteTo.Seq("http://localhost:5341", apiKey: "xxx"),否则只收到纯文本,Properties字段为空 - 用
.Filter.ByExcluding(Matching.WithProperty("SourceContext", "Microsoft.*"))屏蔽框架日志(可选)
全局上下文和请求级属性怎么加才不漏
LogContext.PushProperty 是线程本地的,中间件里加了,但没在每个请求开始时触发,就会导致部分日志缺失 CorrelationId 或 RequestPath。
实操建议:
- 启动时加固定属性:
LogContext.PushProperty("App", "OrderService") - ASP.NET Core 中,用
UseSerilogRequestLogging()中间件(需装Serilog.AspNetCore),它会自动注入RequestPath、StatusCode、Elapsed等 - 自定义属性如
UserId,应在认证后、进入业务逻辑前,用LogContext.PushProperty("UserId", userId)——别放在 Action 里,否则异步操作可能已脱离作用域
最容易被忽略的是:每次调用 Log.ForContext<t>()</t> 都生成新 logger 实例,高频创建会引发 GC 压力;真正需要子上下文时,优先用 LogContext 或 BeginScope。










