C#.NET Serilog 详解
Serilog 是 .NET 生态中强大的结构化日志记录库,通过事件属性和丰富输出格式,显著提升日志的可分析性和可观测性。以下是核心概念与使用详解:
一、核心特性
- 结构化日志
将日志转化为键值对数据结构:
Log.Information("订单 {OrderId} 处理完成,金额:{Amount}", order.Id, order.Total);
输出为结构化数据(如 JSON),便于 ELK/Splunk 等工具分析。
- 灵活的 Sink 系统
支持 100+ 输出目标:
- 控制台:
Serilog.Sinks.Console
- 文件:
Serilog.Sinks.File
- Seq:
Serilog.Sinks.Seq
(专为 Serilog 设计的日志服务器) - Elasticsearch/数据库/Email 等
- 动态日志级别
运行时动态调整日志级别:
Log.Logger = new LoggerConfiguration()
.MinimumLevel.ControlledBy(new LoggingLevelSwitch(LogEventLevel.Information)) // 初始级别
.CreateLogger();
// 运行时动态调整为 Debug
var levelSwitch = Log.Logger.GetLevelSwitch();
levelSwitch.MinimumLevel = LogEventLevel.Debug;
二、基础配置
using Serilog;
// 创建 Logger
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug() // 全局最小日志级别
.WriteTo.Console() // 输出到控制台
.WriteTo.File("logs/log-.txt",
rollingInterval: RollingInterval.Day) // 每日滚动日志
.Enrich.WithThreadId() // 附加线程ID
.CreateLogger();
// 记录日志
Log.Information("服务启动");
Log.Error(ex, "处理订单失败,ID: {OrderId}", orderId);
// 程序退出时释放资源
Log.CloseAndFlush();
三、高级功能
- 日志上下文增强
使用LogContext
附加上下文信息:
using (LogContext.PushProperty("RequestId", Guid.NewGuid()))
{
Log.Information("处理请求"); // 自动附加 RequestId
}
- 自定义输出模板
控制日志格式:
.WriteTo.Console(outputTemplate:
"[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj} {Properties}{NewLine}{Exception}")
- 异步日志写入
使用缓冲队列提升性能:
.WriteTo.Async(a => a.File("logs/async-log.txt"))
- 日志过滤
按条件过滤日志:
.Filter.ByExcluding(e => e.Properties["SourceContext"].ToString().Contains("NoisyComponent"))
四、与依赖注入集成
在 ASP.NET Core 中配置:
// Program.cs
builder.Host.UseSerilog((ctx, config) =>
config.ReadFrom.Configuration(ctx.Configuration));
// appsettings.json
{
"Serilog": {
"MinimumLevel": "Information",
"WriteTo": [
{ "Name": "Console" },
{
"Name": "File",
"Args": { "path": "logs/log.txt" }
}
],
"Enrich": [ "WithThreadId" ]
}
}
五、最佳实践
- 异常日志标准化
始终传递异常对象:
try { /* ... */ }
catch (Exception ex) {
Log.Error(ex, "操作失败"); // 包含堆栈信息
}
- 避免字符串拼接
使用模板参数代替拼接:
// 推荐
Log.Debug("用户 {UserId} 登录", user.Id);
// 避免
Log.Debug($"用户 {user.Id} 登录"); // 影响性能
- 关键业务附加属性
为关键操作添加业务维度:
Log.ForContext("Order", new { order.Id, order.Status })
.Information("订单状态更新");
六、性能优化
- 使用
Logger.IsEnabled(LogLevel)
避免高开销操作:
if (Log.IsEnabled(LogEventLevel.Debug)) {
var data = ExpensiveDataQuery();
Log.Debug("数据: {Data}", data);
}
- 异步 Sink 减少 I/O 阻塞
- 控制日志量(避免 Verbose 级生产环境日志)
通过结构化日志和丰富生态系统,Serilog 显著提升 .NET 应用的运维效率和故障排查能力。建议结合 Seq 或 ELK 实现可视化日志分析。