日志级别与分类:Error、Warning、Info、Debug的区别
日志这东西,说白了就是程序运行时的「黑匣子」。我做了十几年嵌入式开发,见过太多工程师把日志当成可有可无的东西。直到有一次,一个产品在客户现场死机,没有日志可查,我们团队硬是花了三周才复现问题。嗯,从那以后,我对日志的态度彻底变了。
今天咱们聊聊日志的四个核心级别:Error、Warning、Info、Debug。别小看这几个词,用好了能救命,用不好就是噪音。
一、四个级别的本质区别
先看一张图,这是我个人习惯的分类方式:
从上往下看,严重程度递减,但信息详细程度递增。这个金字塔结构,我建议你记在心里。
二、每个级别详解
1. Error(错误)—— 红色警报
Error 级别的日志,意味着程序遇到了无法自行恢复的问题。比如内存分配失败、文件打不开、硬件初始化失败。这时候程序要么崩溃,要么进入一个降级模式。
我在项目中遇到过最典型的例子:一个嵌入式设备在野外运行,突然所有传感器都报 Error。查日志发现只写了「sensor error」,没有具体是哪个传感器、什么错误码。结果工程师只能带着设备去现场,插上调试器重新跑一遍。你说这多耽误事?
// 好的做法
log_error("ADC初始化失败: 设备ID=%d, 错误码=0x%X, 寄存器状态=0x%X",
dev_id, err_code, reg_status);
// 不好的做法
log_error("ADC error");
2. Warning(警告)—— 黄色预警
Warning 表示「有问题,但程序还能跑」。比如电池电量低于20%、网络重试次数过多、某个配置项使用了默认值。这些信息很重要,因为它们往往是潜在故障的前兆。
举个例子:一个通信模块偶尔丢包,如果只打 Warning,可能几个月都没人管。直到某天丢包率超过阈值,系统直接宕机。你想想看,如果早点处理 Warning,是不是能避免这个事故?
// 合理的 Warning 使用
if (retry_count > 3) {
log_warning("TCP连接重试次数过多: 已重试%d次, 目标IP=%s",
retry_count, ip_addr);
}
3. Info(信息)—— 蓝色常规
Info 记录的是程序的关键运行节点。比如「系统启动完成」「配置文件加载成功」「用户登录成功」。这些信息用于追踪程序的正常流程,是运维和问题排查的基础。
我个人习惯把 Info 日志控制在每秒钟不超过10条。太多会刷屏,太少又查不到线索。这个平衡点需要根据具体场景调整。
// Info 日志示例
log_info("系统启动完成: 固件版本=%s, 运行模式=%s, 内存使用=%dKB",
firmware_ver, mode, mem_usage);
4. Debug(调试)—— 绿色细节
Debug 日志是最详细的,包含函数调用参数、中间变量值、循环迭代次数等。这些信息只在开发和调试阶段有用,正式发布时必须关闭。
// 使用条件编译控制 Debug 日志
#ifdef DEBUG_ENABLE
log_debug("函数process_data被调用: input=%d, threshold=%d",
input_val, threshold);
#endif
三、不同级别的处理策略
| 级别 | 处理策略 | 存储方式 | 响应方式 |
|---|---|---|---|
| Error | 立即处理,触发告警 | 持久化存储,保留至少30天 | 短信/邮件/蜂鸣器报警 |
| Warning | 定期分析,记录趋势 | 持久化存储,保留7天 | 日志系统标记,每日汇总 |
| Info | 按需查看,用于追踪 | 循环覆盖,保留最近10000条 | 不主动通知 |
| Debug | 仅在开发阶段启用 | 内存缓冲,不落盘 | 不通知 |
四、避坑指南
我曾经犯过一个低级错误:把所有日志都打成 Error 级别。结果系统一跑,满屏都是红色。真正出问题的时候,反而没人看了。这叫「狼来了」效应。
还有一次,我把敏感信息写进了 Debug 日志,比如用户密码的明文。结果代码开源后,被人扒了个底朝天。嗯,这个教训让我养成了一个习惯:日志里永远不要出现密码、密钥、个人隐私数据。
- 用户密码、Token、Session ID
- 银行卡号、身份证号
- 完整的 SQL 语句(可能泄露表结构)
- 内存原始数据(可能包含敏感信息)
五、实际项目中的配置示例
下面是我在一个物联网网关项目中的日志配置,你可以参考:
// 日志级别配置结构体
typedef struct {
log_level_t level; // 当前日志级别
bool to_console; // 是否输出到控制台
bool to_file; // 是否写入文件
bool to_remote; // 是否发送到远程服务器
uint32_t file_size; // 单个日志文件大小限制
uint32_t file_count; // 日志文件轮转数量
} log_config_t;
// 生产环境配置
log_config_t prod_config = {
.level = LOG_LEVEL_INFO, // 只记录 Info 及以上
.to_console = false, // 不输出到控制台
.to_file = true, // 写入文件
.to_remote = true, // 发送到远程
.file_size = 10 * 1024 * 1024, // 每个文件10MB
.file_count = 10 // 保留10个文件
};
// 调试环境配置
log_config_t debug_config = {
.level = LOG_LEVEL_DEBUG, // 记录所有级别
.to_console = true, // 输出到控制台
.to_file = true, // 同时写入文件
.to_remote = false, // 不发送远程
.file_size = 50 * 1024 * 1024, // 每个文件50MB
.file_count = 5 // 保留5个文件
};
你想想看,如果生产环境开了 Debug 日志,一个设备一天就能产生几个 GB 的日志。不仅浪费存储,还会拖慢系统性能。所以,不同环境用不同配置,这是基本功。
六、总结一下
日志级别不是随便定的。Error 要少而精,Warning 要引起重视,Info 要清晰完整,Debug 要只在需要时开启。我见过太多团队把日志当成「写完就忘」的东西,结果出了问题才后悔莫及。
记住一句话:好的日志系统,能让你在问题发生后的10分钟内定位到根因。差的日志系统,只会让你对着满屏的「unknown error」发呆。
- Error:出了问题能直接定位
- Warning:潜在风险能提前发现
- Info:运行状态能随时掌握
- Debug:调试细节能按需获取
好了,这一章就到这里。日志级别这件事,看似简单,但真正用好的人不多。希望你能从今天开始,认真对待每一行日志。