日志分析入门:日志级别、格式解析与常用框架
日志这东西,说白了就是程序的「黑匣子」。
我刚入行那会儿,觉得日志就是随便打印点东西,方便自己调试。直到有一次线上出了个诡异的内存泄漏,查了三天没头绪。最后是一位老同事翻了半天日志,从几万行 WARN 里揪出了一条关键线索。嗯,从那以后,我再也不敢小看日志了。
今天我们就来聊聊日志分析的基础。你想想看,如果连日志都看不懂,怎么定位缺陷?
一、日志级别:你的程序在「喊」什么?
日志级别,就是给信息贴个标签。告诉你看日志的人:这条信息有多严重。
我个人习惯把日志级别分成四个档次,从轻到重:
| 级别 | 含义 | 什么时候用? |
|---|---|---|
| DEBUG | 调试信息 | 开发阶段,用来跟踪变量、流程。线上环境一般关掉。 |
| INFO | 普通信息 | 记录关键业务节点,比如「用户登录成功」「订单已创建」。 |
| WARN | 警告 | 程序还能跑,但有点不对劲。比如「磁盘空间不足80%」「重试第3次」。 |
| ERROR | 错误 | 程序出问题了,需要人工介入。比如「数据库连接失败」「空指针异常」。 |
核心原则:线上环境只开 INFO 及以上。DEBUG 日志量太大,会拖垮性能。
我在项目中遇到过一件事:有个同事把关键的业务校验逻辑写在 DEBUG 日志里。结果线上环境没开 DEBUG,那个校验根本没执行。你说坑不坑?
避坑指南:我曾经见过有人把「用户密码错误」这种敏感信息打在 INFO 级别。结果日志被运维同学不小心发到了群里。嗯,隐私问题,一定要注意。
二、日志格式解析:别让信息「裸奔」
日志光有内容不够,还得有「身份证」。一条合格的日志,应该包含以下信息:
- 时间戳:精确到毫秒。方便定位问题发生的时间点。
- 线程名:多线程环境下,知道是哪个线程出的问题。
- 日志级别:一目了然。
- 类名/方法名:快速定位代码位置。
- 消息内容:具体发生了什么。
举个例子,一条典型的 Logback 日志长这样:
2025-03-21 14:32:18.456 [http-nio-8080-exec-3] INFO com.example.OrderService - 订单创建成功,订单号:ORD20250321001
你想想看,如果没有时间戳,你怎么知道这个错误是今天发生的还是上周的?如果没有线程名,并发场景下你根本分不清谁是谁。
我的小技巧:我个人习惯在日志里加上「请求ID」或者「TraceID」。这样一次用户请求的所有日志都能串起来。排查问题时,一条命令就能把整个调用链拉出来。
三、常用日志框架:Log4j 与 Logback
Java 世界里,日志框架就那几家。我重点说说 Log4j 和 Logback。
3.1 Log4j:老牌劲旅
Log4j 是 Apache 的项目,出道早,用的人多。配置方式比较传统,用 .properties 文件。
一个简单的 log4j.properties 示例:
# 设置根日志级别为 INFO,输出到控制台和文件
log4j.rootLogger=INFO, console, file
# 控制台输出
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} [%t] %-5p %c{1} - %m%n
# 文件输出
log4j.appender.file=org.apache.log4j.RollingFileAppender
log4j.appender.file.File=logs/app.log
log4j.appender.file.MaxFileSize=10MB
log4j.appender.file.MaxBackupIndex=5
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} [%t] %-5p %c{1} - %m%n
这里要注意 RollingFileAppender。它会在文件达到 10MB 时自动滚动,保留最近 5 个备份。防止日志文件撑爆磁盘。
避坑指南:我曾经见过有人把 MaxBackupIndex 设成 0。结果日志文件越滚越大,最后把磁盘写满了。嗯,这个参数一定要设个合理的值。
3.2 Logback:Log4j 的升级版
Logback 是 Log4j 的作者写的另一个框架。性能更好,功能更强。现在 Spring Boot 默认就用它。
Logback 用 logback.xml 配置。举个例子:
<configuration>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>logs/app.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>logs/app.%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="FILE"/>
</root>
</configuration>
Logback 有个很实用的功能:根据日志级别输出到不同文件。比如 ERROR 日志单独存一个文件,方便排查。
<appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>logs/error.log</file>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>ERROR</level>
</filter>
<!-- 其他配置略 -->
</appender>
我的建议:我个人习惯把 ERROR 日志单独拎出来。线上出问题时,直接 tail -f error.log,不用在 INFO 的海洋里捞针。
四、知识体系一览
说了这么多,我画张图帮你理一理。日志分析的核心就这三块:
说白了,日志分析就是三个步骤:看级别 → 读格式 → 用框架。级别告诉你严重程度,格式告诉你上下文,框架帮你把日志管好。
我个人觉得,日志这东西,前期多花点心思配置好,后期能省下大把时间。你想想看,线上出问题时,别人还在翻山越岭找日志,你一条命令就定位到了。那种感觉,嗯,挺爽的。
一句话总结:日志不是写给机器看的,是写给未来的自己看的。别偷懒,好好配。