日志基础与规范:日志级别、格式标准化与轮转策略
日志这东西,说白了就是系统的黑匣子。你想想看,线上出了故障,第一反应是什么?肯定是翻日志。但如果日志乱七八糟,级别乱用、格式不统一、文件撑爆磁盘……那这黑匣子还不如没有。今天我就把日志基础这块掰开揉碎了讲清楚。
2.1 日志级别:DEBUG / INFO / WARN / ERROR
日志级别不是拍脑袋定的,它有一套通用的语义。我个人习惯把这四个级别当成「信号灯」来看:
| 级别 | 含义 | 典型场景 | 生产环境是否开启 |
|---|---|---|---|
| DEBUG | 调试信息,开发阶段用 | 变量值、函数入口/出口、SQL 参数 | ❌ 关闭 |
| INFO | 正常业务流程记录 | 服务启动、请求到达、任务完成 | ✅ 开启 |
| WARN | 潜在问题,不影响当前运行 | 配置降级、重试、超时阈值接近 | ✅ 开启 |
| ERROR | 明确错误,需要人工介入 | 数据库连接失败、空指针、业务异常 | ✅ 开启 |
我曾经踩过一个坑: 有同事把所有的异常都打成了 ERROR,包括一些业务上预期的「用户输入不合法」。结果告警平台天天炸,真正的 ERROR 反而被淹没了。记住,ERROR 只留给「系统无法自动恢复」的情况。
级别之间还有一条潜规则:向上兼容。你设置了日志级别为 WARN,那么 DEBUG 和 INFO 就不会输出。这能帮你控制日志量,避免磁盘被刷爆。
2.2 日志格式标准化
日志格式不统一,解析工具根本没法用。我见过最离谱的日志,时间戳格式一天一变,有的用 ISO 8601,有的用 Unix 时间戳,还有的干脆写「昨天下午三点」。嗯,这种日志基本等于废纸。
标准化格式长什么样?我推荐一个通用模板:
[时间戳] [日志级别] [线程名] [类名:行号] - 消息内容
举个例子:
[2025-03-21 14:32:18.123] [INFO] [http-nio-8080-exec-3] [com.example.OrderService:56] - 订单 20250321143218001 创建成功,金额 299.00 元
这里面每个字段都有用:
- 时间戳:精确到毫秒,格式统一用
yyyy-MM-dd HH:mm:ss.SSS - 日志级别:固定宽度,方便 grep 过滤
- 线程名:排查并发问题必备
- 类名:行号:定位代码位置
- 消息内容:包含关键业务标识(订单号、用户 ID)
我建议: 在消息内容里加上 traceId 或 requestId。这样一次请求的所有日志都能串起来,排查链路问题会轻松很多。
2.3 日志切分与轮转策略
日志文件如果不切分,一个月下来能撑到几十 GB。到时候别说分析,连打开都费劲。切分和轮转就是为了解决这个问题。
常见的切分方式有两种:
- 按时间切分:每天一个文件,比如
app-2025-03-21.log - 按大小切分:每个文件 100MB,满了就切下一个
轮转策略就是「切分之后怎么处理旧文件」。我一般用 保留最近 N 个文件 的策略:
| 策略 | 说明 | 适用场景 |
|---|---|---|
| 保留数量 | 只保留最近 7 个文件,旧的自动删除 | 磁盘空间紧张 |
| 保留天数 | 保留最近 30 天的日志 | 合规审计要求 |
| 压缩归档 | 切分后 gzip 压缩,保留更久 | 历史追溯需求 |
以 Logback 为例,配置一个按天切分、保留 30 天的策略:
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>/var/log/app/app.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>/var/log/app/app-%d{yyyy-MM-dd}.log.gz</fileNamePattern>
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%level] [%thread] [%logger{36}:%line] - %msg%n</pattern>
</encoder>
</appender>
注意: 切分时机要避开业务高峰期。我曾经在双十一凌晨 0 点切分日志,结果切分时文件锁导致业务线程阻塞了 3 秒。后来我把切分时间改到了凌晨 4 点,再也没出过问题。
2.4 知识体系总览
下面这张图把日志基础的核心逻辑串起来了。你可以把它当成一个检查清单:
总结一下:
- 日志级别要严格区分,ERROR 只留给真正的错误
- 格式标准化是日志分析的基础,时间戳、级别、线程、类名缺一不可
- 切分和轮转能避免磁盘爆满,同时保留足够的历史数据
这些规范看起来简单,但真正落地需要团队共识和工具配合。我见过太多项目因为日志不规范,排查问题时两眼一抹黑。别让你的系统也变成那样。