日志系统设计原则:日志级别、格式规范与存储策略
做运动控制调试这么多年,我踩过最大的坑,就是日志系统没设计好。
记得有一次,现场设备跑着跑着突然报错,我翻遍了几百MB的日志文件,全是INFO级别的“正常运转”信息。真正有用的ERROR信息,早就被刷没了。那一刻我就在想——日志系统,真不是随便写写就行的。
今天咱们就聊聊日志系统的三个核心设计原则:日志级别、日志格式、日志存储策略。说白了,就是让你在出问题时,能快速找到关键信息。
一、日志级别:给信息分个优先级
日志级别,就是给每条日志贴个标签。告诉系统:这条信息有多重要。
我个人习惯用四个级别,够用且不复杂:
| 级别 | 含义 | 典型场景 |
|---|---|---|
| DEBUG | 调试信息 | 变量值、函数入口/出口、循环次数 |
| INFO | 常规信息 | 系统启动、参数加载、任务完成 |
| WARN | 警告信息 | 参数超限、通信超时、资源不足 |
| ERROR | 错误信息 | 电机堵转、通信中断、内存溢出 |
DEBUG:开发时用,上线后关掉。我在项目中遇到过,有人把DEBUG日志开到了生产环境,结果一天写了10GB日志,硬盘直接爆了。
INFO:记录系统正常运转的关键节点。比如“轴1启动”、“位置到达目标”。
WARN:系统还能跑,但有点不对劲。比如“通信重试第3次”。我曾经因为忽略WARN日志,导致一台伺服电机连续抖动了一周才被发现。
ERROR:必须立刻处理的问题。比如“驱动器报错:过流”。
核心原则:生产环境只开INFO及以上级别。DEBUG日志只在调试时开启。
二、日志格式规范:让信息一目了然
日志格式,说白了就是每条日志长什么样。我见过最乱的日志,连时间戳都没有,根本不知道问题发生在什么时候。
我建议的格式:
[时间戳] [级别] [模块] [线程ID] 消息内容
举个例子:
[2025-01-15 14:23:45.678] [ERROR] [Axis1] [TID:1234] 电机堵转,当前位置: 1234.56mm
为什么这么设计?
- 时间戳:精确到毫秒,方便定位问题发生的时间点
- 级别:一眼看出严重程度
- 模块:知道是哪个组件出的问题
- 线程ID:多线程调试时,知道是哪个线程在干活
- 消息内容:关键信息要带上上下文数据
我的小技巧:时间戳用ISO 8601格式(YYYY-MM-DD HH:mm:ss.SSS),跨平台解析方便。别用自定义格式,否则换系统就抓瞎。
三、日志存储策略:别让日志撑爆硬盘
日志存储,是个容易被忽视的问题。你想想看,运动控制系统一天跑下来,日志量可能上GB。如果不做管理,硬盘迟早会满。
我常用的三种策略:
1. 按大小滚动
每个日志文件固定大小,比如10MB。写满后自动创建新文件。旧文件可以保留N个,超出的自动删除。
// 伪代码示例
log_file_size = 10MB
max_backup_files = 5
// 当当前文件达到10MB时,创建新文件,删除最旧的文件
2. 按时间滚动
每天一个日志文件,或者每小时一个。适合需要按时间维度查问题的场景。
// 日志文件名示例
control_2025-01-15.log
control_2025-01-16.log
3. 按级别分离
ERROR日志单独存一个文件。这样出问题时,直接看ERROR文件,不用在INFO里翻来翻去。
// 文件结构
logs/
info.log // INFO及以上
error.log // 仅ERROR
debug.log // 仅DEBUG(调试时开启)
注意:千万别把日志写到系统盘(C盘)。我曾经见过有人把日志写到C盘,结果日志把系统盘撑爆了,系统直接蓝屏。日志一定要写到独立的数据盘。
四、知识体系总览
下面这张图,把日志系统的核心逻辑串起来了。你看一眼就明白:
五、避坑指南
最后,分享几个我踩过的坑:
- 别在日志里打印敏感信息:比如密码、密钥。我曾经见过有人把数据库密码直接打在日志里,结果日志文件被运维人员看到了...尴尬。
- 日志别写得太频繁:每毫秒写一条日志,系统性能直接掉一半。我建议关键事件才写日志,循环体里尽量少写。
- 日志文件要加锁:多线程写日志时,不加锁会导致日志内容错乱。我见过最离谱的,一条日志被拆成了两半,根本没法看。
- 日志目录要定期清理:别指望手动删。写个定时任务,自动清理30天前的日志。
总结一下:日志系统设计,说白了就是三个字——分、规、存。分级别、规格式、存策略。做好了,调试效率翻倍;做不好,出问题就是灾难。
公众号:蓝海资料掘金营,微信deep3321