日志基础与规范:日志级别、格式标准与最佳实践
聊到日志驱动的性能瓶颈定位,咱们得先把地基打牢。日志这东西,写得好是救命稻草,写得烂就是噪音污染。我见过太多团队,日志打了一堆,出问题的时候两眼一抹黑——说白了,就是没按规矩来。
今天咱们就掰扯清楚三个核心问题:日志级别怎么分、格式怎么写、以及那些我踩过的坑。
日志级别:别把DEBUG当ERROR用
日志级别这事儿,看似简单,但我在项目中见过最离谱的——有人把数据库连接失败打成了INFO级别。你想想看,生产环境出这种问题,运维根本不会注意到。嗯,这里要注意,级别选错了,等于没打。
标准的分级是这样的:
| 级别 | 含义 | 典型场景 | 我个人的建议 |
|---|---|---|---|
| DEBUG | 调试信息 | 变量值、循环次数、函数入参 | 只在开发环境开启,生产环境关掉 |
| INFO | 正常流程 | 服务启动、请求开始/结束、配置加载 | 保留关键业务路径,别什么都打 |
| WARN | 潜在问题 | 重试、降级、超时阈值接近 | 需要关注但不影响当前请求 |
| ERROR | 明确故障 | 异常捕获、调用失败、数据不一致 | 必须包含上下文,别只打个null |
我曾经接手过一个系统,ERROR日志一天能刷几十万条。一查,全是某个接口的超时重试——但重试成功了,代码里却打了ERROR。这叫什么?这叫狼来了。真正出问题的时候,没人会去看日志了。
日志格式标准:结构化才是王道
很多团队的日志长这样:2024-01-01 12:00:00 用户登录失败。你告诉我,哪个用户?哪个IP?失败原因是什么?全都没有。这种日志,说白了就是废纸。
我个人习惯用JSON格式,结构清晰,解析方便。举个例子:
{
"timestamp": "2024-01-01T12:00:00.123Z",
"level": "ERROR",
"traceId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"service": "user-service",
"class": "com.example.UserController",
"method": "login",
"message": "用户登录失败",
"userId": "u_10086",
"ip": "192.168.1.100",
"errorCode": "AUTH_001",
"duration": 2345,
"extra": {
"attemptCount": 3,
"lastFailureReason": "密码错误"
}
}
你想想看,有了traceId,你就能把一次请求的所有日志串起来。有了duration,你一眼就能看出哪个接口慢。有了errorCode,告警系统可以直接分类处理。
这里有个关键点——时间戳一定要带时区。我遇到过分布式系统跨时区部署,日志时间差了8个小时,排查问题的时候差点把服务器砸了。用UTC+0,或者明确标注时区,别含糊。
日志最佳实践:少打、精打、打对地方
日志不是越多越好。我见过一个项目,一个请求能打出200行日志。结果磁盘IO成了瓶颈,性能反而下降了。记住三个原则:
- 关键路径必打:请求入口、出口、数据库操作、外部调用
- 异常场景必打:捕获异常时,把异常栈和上下文一起打出来
- 循环内慎打:循环里打DEBUG日志,量级会爆炸
举个例子,一个常见的错误写法:
// 错误示范:循环里打日志
for (Order order : orderList) {
log.debug("处理订单: {}", order.getId());
process(order);
}
如果orderList有10万条,这日志量直接起飞。正确的做法是:
// 正确示范:只打汇总信息
log.info("开始批量处理订单, 总数: {}", orderList.size());
long start = System.currentTimeMillis();
for (Order order : orderList) {
process(order);
}
long cost = System.currentTimeMillis() - start;
log.info("批量处理完成, 总数: {}, 耗时: {}ms", orderList.size(), cost);
你看,这样既知道了处理量,又知道了耗时,还不会产生海量日志。说白了,日志是给人看的,不是给硬盘看的。
关于日志级别的几个实战建议
最后分享几个我这些年总结出来的小经验:
- ERROR级别一定要有处理人:打ERROR意味着需要人工介入。如果没人看,就别打ERROR。
- WARN级别要设置阈值:比如某个接口WARN日志超过100次/分钟,自动升级为告警。
- INFO级别要控制量:我一般要求单个请求的INFO日志不超过10条。超过这个数,就得考虑是不是打得太多了。
- DEBUG级别要能动态开关:线上环境默认关闭,但可以通过配置中心动态开启。这样排查问题时可以临时打开,用完再关。
嗯,日志这东西,看着简单,但真正做好的人不多。你想想看,一个系统跑了一年,日志文件几十个G,但出问题的时候你连根毛都找不到——这种痛苦,经历过的人都懂。
下一章咱们聊聊怎么从日志里快速定位性能瓶颈,到时候我会分享一个我亲手搭建的日志分析工具链,保证实用。