第10章:日志系统概述——为什么需要日志?
说实话,我见过太多团队把日志当成「可有可无」的东西。
项目初期,大家忙着写业务代码。日志?随便打几条就行。等到线上出了故障,一群人对着控制台干瞪眼。那种感觉,我经历过不止一次。
日志不是写给机器看的。它是写给「未来的你」看的。那个凌晨三点被电话叫醒的你,那个面对用户投诉却无从下手的你。
为什么需要日志?
简单说,日志就是系统的「黑匣子」。飞机出事要找黑匣子,系统出问题就要翻日志。
具体来说,日志有这几个核心作用:
- 故障排查:系统崩了,你总得知道崩在哪吧?日志就是第一手线索。
- 性能分析:哪个接口慢?哪个SQL耗时?日志里一清二楚。
- 安全审计:谁在什么时候做了什么操作?日志是铁证。
- 业务监控:订单量、用户活跃度,这些都能从日志里提炼出来。
我的经验:有一次线上服务频繁重启,排查了两小时没头绪。最后翻出GC日志,发现是内存泄漏。如果当时没开日志,这问题可能得折腾一整天。
日志的级别
日志级别不是随便定的。每个级别都有它的使用场景。我见过有人把所有日志都打成Info,结果生产环境一天几个G的日志,真正有用的信息全被淹没了。
| 级别 | 含义 | 使用场景 | 我建议 |
|---|---|---|---|
| Trace | 最详细的跟踪信息 | 开发调试,几乎不用在生产环境 | 开发环境开,生产环境关 |
| Debug | 调试信息 | 开发阶段,定位具体代码路径 | 测试环境可以开,生产慎用 |
| Info | 常规信息 | 记录系统正常运行状态 | 生产环境主力,但别滥用 |
| Warn | 警告 | 潜在问题,不影响当前运行 | 一定要关注,往往是故障前兆 |
| Error | 错误 | 功能不可用,需要人工介入 | 必须告警,不能忽略 |
| Fatal | 致命错误 | 系统即将崩溃或已崩溃 | 立刻通知值班人员 |
避坑指南:我曾经在一个项目里,把数据库连接失败打成了Warn级别。结果连接池耗尽,服务挂了,告警系统却没触发。从那以后,凡是影响核心功能的异常,我至少打Error。
日志框架选型
.NET生态里,主流的日志框架就三个:NLog、Serilog、Log4Net。选哪个?我个人的经验是:看场景。
NLog
老牌框架,稳定可靠。配置灵活,性能也不错。我最早用的就是它。
- 优点:配置简单,上手快,文档齐全
- 缺点:结构化日志支持一般,扩展性不如Serilog
- 适合:中小型项目,传统架构
Serilog
现在最火的日志框架。它的核心思想是「结构化日志」。
- 优点:原生支持结构化,和ELK、Seq等配合完美
- 缺点:学习曲线稍陡,配置项多
- 适合:微服务、云原生、需要集中式日志分析的场景
Log4Net
从Java移植过来的老将。现在用的人越来越少了。
- 优点:稳定,配置方式和Log4j一致
- 缺点:性能一般,社区活跃度低
- 适合:遗留系统维护,或者团队有Java背景
我的选择:新项目我基本都用Serilog。为什么?因为现在做全链路监控,日志必须结构化。你想想看,如果日志只是一堆字符串,你怎么做关联分析?怎么做链路追踪?Serilog的@操作符能把对象序列化成结构化数据,这一点太香了。
一个简单的Serilog示例
光说不练假把式。我贴一段实际项目里的配置代码:
// 安装包:Serilog.AspNetCore, Serilog.Sinks.Console, Serilog.Sinks.File
using Serilog;
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Information()
.MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
.WriteTo.Console()
.WriteTo.File("logs/myapp-.log", rollingInterval: RollingInterval.Day)
.Enrich.WithProperty("Application", "MyApp")
.CreateLogger();
try
{
Log.Information("应用启动");
CreateHostBuilder(args).Build().Run();
}
catch (Exception ex)
{
Log.Fatal(ex, "应用启动失败");
}
finally
{
Log.CloseAndFlush();
}
这段代码做了几件事:
- 只记录Info及以上级别的日志
- 把微软自家的日志降到Warn,避免刷屏
- 同时输出到控制台和文件
- 每天滚动一个日志文件
- 给每条日志打上应用名标签
注意:Log.CloseAndFlush()一定要写在finally块里。我见过有人忘了这行,结果应用退出时日志没刷完,丢了几条关键信息。排查问题的时候,那叫一个抓狂。
小结
日志这事,说简单也简单,说复杂也复杂。简单的是API调用,复杂的是怎么用好它。
我的建议是:
- 先选一个框架用起来,别纠结
- 级别要分清楚,别什么都打Info
- 结构化日志是趋势,早点上手
- 日志不是写完了就完事,要有人看、有人分析
下一章,我会讲怎么把日志和全链路监控结合起来。到时候你就知道,日志不只是「记录」,更是「洞察」。