日志系统设计原则

日志系统这东西,说白了就是飞控系统的「黑匣子」。我做了这么多年飞控中间件,最怕的就是系统在空中出了故障,结果日志一塌糊涂,根本查不出原因。嗯,今天我们就聊聊日志系统该怎么设计。

日志级别:从DEBUG到ERROR

日志级别不是随便定的。我个人习惯用四个级别,刚好够用,多了反而乱。

级别 含义 我什么时候用
DEBUG 调试信息 开发阶段、排查问题时才开启
INFO 常规信息 系统启动、参数变更、任务切换
WARN 警告 异常但不影响运行的情况
ERROR 错误 必须人工介入的故障

核心原则:生产环境只开INFO及以上级别。DEBUG日志量太大,会拖慢系统。

我在项目中遇到过一件事:有个同事把DEBUG日志开到了线上,结果每秒刷出几万条日志,直接把存储写爆了。飞机还在天上飞,日志先挂了。你说冤不冤?

日志格式规范

日志格式这事,看着简单,其实坑很多。我见过最乱的日志,连时间戳都没有,根本没法分析。

我个人推荐的标准格式:

[时间戳] [级别] [模块] [线程ID] - 消息内容

举个例子:

[2024-01-15 14:32:18.456] [INFO] [IMU] [0x3A2F] - 陀螺仪数据校准完成,偏置: 0.02°/s

为什么要这么设计?你想想看:

  • 时间戳:精确到毫秒,方便定位问题发生的时间点
  • 级别:一眼看出严重程度
  • 模块:快速定位是哪个子系统出了问题
  • 线程ID:多线程环境下,知道是谁在干活

我的小技巧:时间戳统一用UTC+8,别用本地时间。有一次我调试跨时区的系统,日志时间乱成一锅粥,后来统一用UTC+8就再没出过问题。

日志轮转策略

日志不能无限增长,否则磁盘迟早会满。轮转策略就是解决这个问题的。

我常用的策略有两种:

  1. 按大小轮转:每个日志文件固定大小,比如100MB。满了就新建一个。
  2. 按时间轮转:每天或每小时生成一个新文件。

实际项目中,我一般两种结合用:

# 日志轮转配置示例
max_file_size: 100MB      # 单个文件最大100MB
max_file_count: 10        # 保留最近10个文件
rotation_policy: size     # 按大小轮转
compress_old: true        # 压缩旧日志

注意:轮转时一定要保证原子操作。我曾经遇到过日志写到一半被轮转,结果文件损坏的情况。解决方案是:先写到一个临时文件,轮转完成后再重命名。

日志存储架构

存储架构这块,我踩过不少坑。飞控系统的日志,既要保证实时写入,又要方便事后分析。

我推荐的分层架构:

应用层 → 日志缓冲区 → 本地存储 → 远程归档

具体来说:

  • 应用层:各个模块产生日志,通过统一的API写入
  • 日志缓冲区:内存中的环形缓冲区,防止写入抖动
  • 本地存储:SSD或eMMC,保存最近7天的日志
  • 远程归档:通过MQTT或FTP上传到服务器,长期保存

关键点:缓冲区大小要合理。太小了容易丢日志,太大了浪费内存。我一般设为1MB,够用。

这里我画了一张架构图,帮你理解整个流程:

日志存储架构图 应用层(IMU、GPS、飞控、通信等模块) 日志缓冲区(环形队列,1MB) 异步写入,防止IO阻塞 本地存储(SSD/eMMC,保留7天) 按大小/时间轮转,自动压缩 远程归档(MQTT/FTP,长期保存)

这张图你看懂了吗?数据从应用层产生,先进入缓冲区,再写入本地存储,最后异步上传到远程。每一层都有缓冲和容错机制,保证日志不丢。

避坑指南:我曾经在远程归档上吃过亏。网络不好时,日志上传失败,结果本地存储被撑爆了。后来我加了限速和重试机制,才彻底解决。

好了,日志系统的设计原则就这些。记住一句话:日志是飞控系统的最后一道防线。设计得好,出问题能快速定位;设计得差,出了事连原因都找不到。你自己掂量掂量。


公众号:蓝海资料掘金营,微信deep3321