一文理清日志输出与轮转清理:从规范到实践
写作注释: 本文由 AI 生成, 主题「浅谈日志: 输出规范与轮转清理」, 内容仅供参考, 欢迎留言交流。
开头引入
日志是软件系统的“黑匣子”,也是排查线上故障的第一手资料。然而在实际开发中,日志往往呈现两个极端:要么惜字如金,出问题时无迹可寻;要么啰嗦冗余,磁盘被几天撑爆。这篇文章想和你聊聊日志这件事——前半部分聚焦输出规范,聊一聊什么样的日志是好日志;后半部分聚焦轮转清理,重点解析 logrotate 的配置与常见坑。希望能帮你建立一套可落地的日志管理思路。
日志输出规范的三个核心原则
好的日志输出不是靠自觉,而是靠规范。首先第一条原则是 “面向读者,而非面向作者”。日志的读者可能是未来的你、值班的同事,甚至是一段自动化告警脚本。因此,每条日志都应包含时间戳、日志级别、业务标识(如订单号、设备 ID)以及清晰的描述信息,不要使用诸如 “something wrong” 之类的模糊描述。
第二条原则是 “分级要克制”。Info 和 Error 是最常用的两个级别,但很多人会把 Warning 当作“另一种颜色”的 Info 来用。我建议采用简单的分级策略:Error 表示需要人工介入的异常,Warning 表示可自动恢复的非预期状态,Info 记录关键业务节点。Debug 只允许在本地开发环境开启,严禁在生产环境打印循环内的调试信息。
第三条原则是 “别打敏感信息”。明文密码、完整手机号、支付密钥等严禁入库,更严禁写进日志。如果确实需要追踪链路,可以使用脱敏后的短 ID。这条原则往往被忽视,一旦被审计或造成用户隐私泄漏,后果非常严重。
输出格式与代码最佳实践
日志输出格式应当由团队统一制定,避免各写各的。默认推荐使用 JSON 格式,因为它天生适合被 Elasticsearch 或 Loki 解析和检索。一个典型的 JSON 日志行大致长这样:
1 | |
如果团队尚无统一框架,Python 项目中可以使用标准库 logging 搭配自定义的 JSON Formatter 快速实现:
1 | |
在实际输出时,务必避免在一个循环里重复拼字符串,也不要将大对象整体序列化后塞进日志。应当把底层异常 e 作为 exc_info=True 传入 logger,既保留堆栈,又不会导致代码里堆出大片 str(e) 拼接逻辑。
日志文件的切割策略
日志文件如果不做切割,会一直膨胀下去,最终拖垮磁盘和 IO。所谓切割,就是按时间或按大小将日志拆分到多个文件。时间型切割按小时、天或周滚动,例如 app-2025-01-04.log;大小型切割则是在文件达到指定阈值时触发滚动,例如 100MB。
实际生产环境中,两者往往结合使用。建议按天切割,同时设置单文件大小上限作为兜底。比如某高并发服务如果一天产生 5GB 日志,又用默认的 RotatingFileHandler,那单个文件体积会大到文本编辑器都打不开——此时必须设置单文件 200MB 就滚动,并保留最近 7 天的旧文件。
实现上,Linux 环境最常用的方案是 logrotate,它不需要你修改任何业务代码,只需在 /etc/logrotate.d/ 下新建一个配置文件即可。这也是下面我要重点展开的部分。
用好 logrotate 进行轮转清理
logrotate 的策略配置非常直观,一个最简洁的示例是这样的:
1 | |
各指令的含义:daily 表示每天轮转一次;rotate 14 表示保留最近 14 份归档日志,稍早的会自动删除;compress 使用 gzip 压缩归档文件(对 .log 文件非常有效);delaycompress 则保证最近生成的归档文件先不压缩,以便排查脚本仍能读取昨天的日志;missingok 避免日志文件缺失时报错;notifempty 表示空文件不轮转;copytruncate 是业务进程无法接收信号重开日志文件时的折中方案,它会先复制再清空,代价是可能丢失极少量的落盘数据。
再顺带一提,有时候你配置了 daily,但发现 logrotate 每天只跑一次且是在凌晨 3 点左右,这是因为系统自带的 cron 定时任务在统一调度它。若需要更高频的轮转,则需要自己额外配置 hourly 的 crontab,这里不展开细说。配置完成后,可通过 sudo logrotate -vf /etc/logrotate.d/your_app 手动强制验证效果,输出会明确显示每条规则是否被正确执行。常见的坑包括忘写 create 指令、日志文件权限被修改、以及 CentOS 与 Ubuntu 的 logrotate 路径差异,这些都需要在落地时仔细比对自己的发行版环境。
日志采集与检索的延伸思考
轮转清理只是日志管理的中间环节,更完整的链路还包括采集与检索。日志被切割后,如果只存放在本地,仍然是信息孤岛。生产环境通常再引入 Filebeat 或 Promtail 将日志文件增量发送到 ES 或 Loki,并配套 Grafana 看板做告警。引入采集器时,要注意日志文件的压缩格式需与采集器兼容,例如某些采集器不支持读取 .gz 压缩包中的增量内容。
同时,也要建立日志归档与冷存储策略:热日志保留最近 7 天,归档日志保存 30 天,超过 30 天的进行冷备至对象存储或直接删除,这样可以显著降低成本。还需要注意的是,容器时代的日志最佳实践是将日志输出到 stdout,由容器运行时统一收集,这样可以规避 Pod 重建后日志丢失的隐患。但无论平台怎么变,良好的日志规范和分级思想永远适用。
总结
日志管理看似微不足道,却直接关系到线上问题的定位效率。我们聊了三个要点:一是规范输出格式与级别,统一结构、透出 traceId、杜绝敏感信息;二是按时间和大小切割文件,避免单个日志无限膨胀;三是熟练使用 logrotate 的轮转与清理策略,并适时引入采集检索链路。建议你现在就检查一遍生产环境的日志配置,确认是否有日志文件正在无限增长、是否有信息裸奔在磁盘上。记住,制定规范比事后弥补要便宜得多——下一次凌晨三点被告警吵醒的时候,你会感谢定下这些规则的自己。