如何在.NET项目中正确安装并初始化Serilog
直接用
NuGet安装两个核心包就够了:
Serilog和对应输出目标的扩展,比如控制台用
Serilog.Sinks.Console,文件用
Serilog.Sinks.File。别装
Serilog.AspNetCore除非你用的是 ASP.NET Core —— 普通 .NET Framework 或 .NET 6+ 控制台项目不需要它。
初始化必须在
Main方法最开头做,早于任何日志调用:
Log.Logger = new LoggerConfiguration()
.WriteTo.Console()
.WriteTo.File("logs/log-.txt", rollingInterval: RollingInterval.Day)
.CreateLogger();
漏掉这句或放错位置,后续所有
Log.Information(...)都会静默失败(不是报错,是根本没输出)。
Serilog.WriteTo.Console() 输出中文乱码怎么办
默认控制台编码是 ANSI,Windows 上常见 GBK 环境下中文变问号。这不是 Serilog 的问题,是
Console自身限制。
解决方式只有两种:
启动程序前执行chcp 65001切换到 UTF-8(临时有效) 在代码里加一句
Console.OutputEncoding = Encoding.UTF8;,且必须放在
Log.Logger = ...之前
注意:.NET Core 3.0+ 默认支持 UTF-8 控制台,但若项目降级兼容旧框架,仍需手动设置。
结构化日志怎么写才真正“结构化”
关键不是用
Log.Information,而是用占位符传参,而不是字符串拼接:
// ✅ 正确:生成带 property 的结构化事件
Log.Information("User {UserId} logged in from {IpAddress}", userId, ip);
// ❌ 错误:只是普通字符串,无字段可查
Log.Information($"User {userId} logged in from {ip}");
这样写之后,日志目标(如 Seq、Elasticsearch)才能把
UserId和
IpAddress当成独立字段过滤或聚合。如果值是对象,Serilog 会自动序列化其公共属性——但别传
this或大集合,容易拖慢性能或泄露敏感数据。
ASP.NET Core 中如何替换默认 ILogger 并注入上下文信息
在
Program.cs(.NET 6+)或
Startup.ConfigureServices(.NET 5 及以前)里,用
UseSerilog()替换掉 Microsoft 的日志系统:
var builder = WebApplication.CreateBuilder(args);
builder.Host.UseSerilog((ctx, lc) => lc
.WriteTo.Console()
.ReadFrom.Configuration(ctx.Configuration));
然后用
ILogger<t></t>注入即可,和原来完全兼容。想自动带上请求 ID、路径等?加
.Enrich.FromLogContext(),并在中间件里用
LogContext.PushProperty:
app.Use(async (ctx, next) =>
{
LogContext.PushProperty("Path", ctx.Request.Path);
await next();
});
不加
Enrich.FromLogContext(),
PushProperty就无效;不配中间件,Web 请求日志就缺上下文——这两步缺一不可。
结构化日志真正的门槛不在配置,而在写日志时是否习惯用命名参数、是否理解
LogContext的作用域边界、以及是否意识到日志输出目标对字段解析能力的依赖。
