日志基础:日志的作用、日志级别与格式规范
聊到分布式系统,我第一个想到的其实是日志。你想想看,一个系统拆成几十上百个服务,出了问题你连它在哪崩的都不知道,那多可怕。日志,说白了就是系统的「黑匣子」。今天我们就来把日志的基础打扎实。
日志到底有什么用?
我个人习惯把日志的作用归纳为三个层面:
- 问题排查:这是最直接的用途。线上出了故障,第一件事就是翻日志。我记得有一次半夜被叫起来,说支付接口超时,我打开日志一看,原来是数据库连接池满了,前后不到五分钟定位问题。
- 系统监控与告警:日志是监控数据的来源之一。比如 ERROR 级别的日志突然暴增,说明系统可能出大事了。我建议每个团队都配一套日志告警规则,别等用户投诉了才去查。
- 业务分析与审计:日志记录了用户的行为轨迹。比如用户下单、退款、修改密码,这些操作日志在审计时就是铁证。我在项目中遇到过,有一次被客户质疑数据对不上,全靠日志还原了操作链路。
一句话总结:没有日志的系统,就像没有仪表盘的飞机。你敢飞,我不敢坐。
日志级别:DEBUG / INFO / WARN / ERROR
日志级别这东西,看似简单,但用错了会出大问题。我见过不少团队,线上环境开着 DEBUG 日志,结果磁盘被撑爆了。嗯,这里要注意,不同级别有不同用途。
| 级别 | 含义 | 使用场景 | 线上是否开启 |
|---|---|---|---|
| DEBUG | 调试信息 | 开发阶段,打印变量值、调用链路细节 | 通常关闭 |
| INFO | 普通信息 | 记录关键业务流程,如请求开始、结束 | 开启 |
| WARN | 警告 | 潜在问题,如磁盘使用率超过80% | 开启 |
| ERROR | 错误 | 系统异常,如数据库连接失败、空指针 | 必须开启 |
DEBUG:说白了就是给开发人员看的。我写代码时习惯在关键分支上打 DEBUG 日志,比如「用户ID=123,进入支付流程」。但线上环境千万别开,否则日志量会爆炸。
INFO:记录业务的关键节点。比如「订单创建成功,订单号=20240301xxxx」。我建议 INFO 日志要让人能看懂业务流程,而不是一堆无意义的字符串。
WARN:系统还能跑,但有点不对劲。比如「重试第3次,仍然失败」。我曾经遇到过,一个接口偶尔超时,WARN 日志帮我提前发现了问题,没等到用户投诉。
ERROR:必须立即处理的问题。比如「数据库连接失败,无法获取数据」。ERROR 日志一定要带上堆栈信息,否则你根本不知道哪里崩了。
避坑指南:我曾经犯过一个错,把业务异常也打成了 ERROR 级别。比如用户输入了错误的密码,这其实是正常流程,打 WARN 就够了。ERROR 应该留给系统级故障,而不是业务逻辑异常。
日志格式规范
日志格式不统一,是分布式系统里最让人头疼的事。你想想看,A 服务用 JSON,B 服务用纯文本,C 服务又用自定义格式,排查问题时简直想骂人。我建议团队统一使用以下格式:
时间戳 | 日志级别 | 服务名 | 线程名 | 请求追踪ID | 类名:行号 | 日志内容
举个例子:
2024-03-01 14:30:22.123 | INFO | order-service | http-nio-8080-exec-1 | trace-abc123 | com.example.OrderService:56 | 订单创建成功,订单号=20240301123456
为什么这么设计?
- 时间戳:精确到毫秒,方便定位问题发生的时间点。
- 日志级别:一眼就能看出问题的严重程度。
- 服务名:分布式系统里,知道是哪个服务出的问题很重要。
- 线程名:排查并发问题时,线程名能帮你理清调用关系。
- 请求追踪ID:这是链路追踪的核心,能把一次请求经过的所有服务串起来。
- 类名:行号:快速定位代码位置,省得你翻半天源码。
我的小技巧:我习惯在日志里加上「业务标识」,比如订单号、用户ID。这样在 Elasticsearch 里搜索时,直接搜订单号就能找到所有相关日志,效率翻倍。
日志内容该写什么?
日志内容不是越多越好,也不是越少越好。我总结了一个原则:能复现问题,就够了。
比如一个支付接口,日志应该包含:
- 请求参数(脱敏后):用户ID、订单号、金额
- 关键处理步骤:调用支付网关、收到回调、更新订单状态
- 异常信息:如果失败,记录错误码和错误描述
- 响应结果:成功或失败,以及耗时
我见过有人把整个请求体都打印出来,里面包含用户密码、银行卡号……这其实很危险。日志里绝对不能出现敏感信息,比如密码、身份证号、银行卡号。我建议在打印前做脱敏处理。
重要提醒:日志是给人看的,不是给机器看的。别写一堆无意义的数字或编码。比如「状态码=1001」,谁知道 1001 是什么意思?不如写成「状态码=1001(支付超时)」,一目了然。
总结一下
日志这东西,平时你可能觉得它不起眼,但真出了问题,它就是你的救命稻草。我个人习惯是:
- DEBUG 日志只在开发环境开
- INFO 日志记录关键业务节点
- WARN 日志关注潜在风险
- ERROR 日志必须立即处理
- 日志格式统一,带上追踪ID
- 敏感信息必须脱敏
下一章我们会聊到日志采集的架构设计,到时候再深入讲讲怎么把日志从各个服务里收集起来。今天就先到这里,记住一句话:日志写得好,下班回家早。