日志级别与分类:DEBUG、INFO、WARN、ERROR、FATAL 的定义与使用场景
日志级别这东西,说白了就是给日志信息贴个标签。告诉看日志的人——这条消息有多严重,该不该立刻处理。
我刚入行那会儿,觉得日志嘛,能打出来就行。结果有一次排查线上问题,满屏都是 INFO,真正关键的 ERROR 被淹没了。从那以后,我才意识到级别划分有多重要。
协议栈里,日志级别通常分五档。从低到高依次是:DEBUG、INFO、WARN、ERROR、FATAL。咱们一个一个说。
DEBUG:开发者的放大镜
DEBUG 级别的日志,只在开发和调试阶段打开。它记录的是最细碎的信息——变量值、函数入口出口、循环次数、状态机跳转细节。
举个例子,你在调试 RRC 连接建立流程:
// 伪代码示例
log_debug("RRCConnectionRequest received, cause=%d, ue_id=%s", cause, ue_id);
log_debug("Entering state: RRC_CONN_SETUP_PENDING");
log_debug("T300 timer started, expiry=%d ms", t300_value);
这些信息在生产环境绝对不能开。为什么?
- 量太大——一秒能刷几千条,磁盘瞬间写满
- 影响性能——频繁 I/O 操作会拖慢协议栈处理速度
- 暴露细节——内部变量、内存地址可能被恶意利用
INFO:正常流程的标记桩
INFO 级别记录的是协议栈正常运行时的关键节点。比如连接建立成功、切换完成、定时器超时后正常处理。
它不表示任何异常,只是告诉你——系统走到这一步了。
log_info("UE context setup complete, RNTI=0x%04x", rnti);
log_info("Handover successful, target cell_id=%d", cell_id);
INFO 日志在生产环境是默认开启的。它用来回答一个最基本的问题:系统现在在干什么?
我记得有一次排查一个小区接入失败的问题。看 INFO 日志发现,UE 的 Attach Request 到了 MME,但 MME 没有回 Attach Accept。这就把问题范围缩小到了核心网侧,而不是空口。
WARN:值得警惕的异常
WARN 表示系统遇到了异常情况,但还能继续运行。它不影响当前功能,但可能埋下隐患。
协议栈里常见的 WARN 场景:
- 重传次数超过阈值但还没到最大限制
- 收到格式异常的协议报文,但还能解析
- 资源池使用率超过 80%
- 定时器超时后重试成功
log_warn("RLC retransmission count=%d, threshold=%d", retx_count, max_retx);
log_warn("SIB1 decoding failed, retrying... attempt=%d", attempt);
ERROR:功能受损,必须介入
ERROR 表示某个功能已经无法正常执行。协议栈会尝试恢复,但用户可能已经感知到服务中断。
典型的 ERROR 场景:
- RRC 连接建立失败
- 安全模式命令失败
- SCTP 链路中断
- 内存分配失败
log_error("RRC connection setup failed, cause=%s", failure_cause);
log_error("SCTP association lost, stream_id=%d", stream_id);
ERROR 日志必须包含足够的信息用于定位。我个人要求团队在 ERROR 日志里至少带上:
- 错误码或失败原因
- 相关的 UE ID 或连接标识
- 当前状态或上下文
光写一句 "RRC setup failed" 等于没写。谁 failed?为什么 failed?在哪个小区?这些信息缺一不可。
FATAL:系统崩溃前的最后遗言
FATAL 是最严重的级别。系统遇到了不可恢复的错误,协议栈即将终止或重启。
什么情况会触发 FATAL?
- 断言失败
- 关键数据结构损坏
- 看门狗超时
- 底层硬件报错
log_fatal("Assertion failed: pdu != NULL, file=%s, line=%d", file, line);
log_fatal("Watchdog timeout, stack will restart");
你想想看,系统都挂了,你只留一句 "FATAL error occurred"。那跟没留有什么区别?
级别对比速查
| 级别 | 含义 | 生产环境 | 典型场景 |
|---|---|---|---|
| DEBUG | 调试信息 | 关闭 | 变量值、函数调用、状态跳转 |
| INFO | 正常流程 | 开启 | 连接建立、切换完成、定时器处理 |
| WARN | 异常但可恢复 | 开启 | 重传超阈值、资源紧张、重试成功 |
| ERROR | 功能失败 | 开启 | 连接失败、链路中断、内存分配失败 |
| FATAL | 系统崩溃 | 开启 | 断言失败、数据结构损坏、看门狗超时 |
日志级别的选择原则
我总结了一个简单的判断方法:
- 这条日志对排查问题有帮助吗?——没有就别打
- 这条日志正常运行时也会出现吗?——是就 INFO,否则 DEBUG
- 出现这条日志需要人关注吗?——需要就 WARN 或 ERROR
- 系统还能继续跑吗?——能就 ERROR,不能就 FATAL
嗯,这里要注意一点。同一个事件在不同阶段可能用不同级别。比如重传:第一次重传可以打 DEBUG,超过阈值打 WARN,达到最大次数后打 ERROR。这叫级别递进,很实用。
日志级别与排查效率
日志级别选对了,排查效率能翻倍。选错了,就是灾难。
我见过一个项目,所有日志都用 INFO。结果线上出问题,日志文件 2GB,根本没法看。后来改成按级别分类,排查时间从小时级降到了分钟级。
还有一个项目,FATAL 日志里只写了 "FATAL"。系统崩溃了,连原因都不知道。这跟没打日志有什么区别?
下面这张图,帮你快速理解五个级别的关系和流向:
从 DEBUG 到 FATAL,严重程度递增,日志量递减。DEBUG 最多,FATAL 最少。这个金字塔结构,你心里要有数。
好了,日志级别就讲到这里。记住一句话:选对级别,比打日志本身更重要。