2. 日志基础:日志级别、日志格式、日志存储

日志这东西,平时不显山不露水。等线上出了故障,你才会发现它有多重要。说白了一句话:日志是你的第二双眼睛。这章咱们就聊聊日志的三大基本功——级别、格式、存储。把这些搞明白,你写规则的时候心里就有谱了。

日志基础体系:从产生到存储 应用程序日志产生 print / logging / logback 日志级别筛选 DEBUG | INFO | WARN | ERROR 日志格式化处理 结构化JSON / 非结构化文本 日志写入输出 文件 / 控制台 / 远程收集 日志轮转与归档 按大小轮转 | 按时轮转 | 压缩保留 💡 核心要点 • 级别决定「记不记」 • 格式决定「好不好解析」 • 存储决定「能不能找到」 • 三者缺一不可 • 规则编写前先定规范

2.1 日志级别 — 你的第一道防线

日志级别这东西,刚入行的人觉得随便设就行。其实不然。我见过太多项目,所有人全用 INFO,结果日志里啥都有,跟垃圾场一样。你想想看,级别设错了,要么漏掉关键信息,要么被海量日志淹死。

常用的级别就这五个:DEBUG、INFO、WARN、ERROR、FATAL。每个级别都有自己的定位。

级别 使用场景 生产建议
DEBUG 开发调试、变量跟踪 默认关闭,按需开启
INFO 业务流程、关键节点记录 开启,但要控制频率
WARN 潜在风险、降级、重试 开启,重点关注
ERROR 业务异常、系统错误 开启,必须告警
FATAL 致命错误、进程退出 开启,立刻告警

我个人习惯在项目里定一条硬规矩:INFO 只记「谁干了什么」,ERROR 只记「哪里出了问题」。别在 INFO 里写变量值,也别在 ERROR 里写业务流程。职责分开,排查问题才快。

小技巧:生产环境把日志级别调到 WARN 以上,能减少 80% 的日志量。需要排查特定问题时,再动态调到 DEBUG。很多日志框架都支持运行时改级别,不用重启。

2.2 日志格式 — 机器和人都在看

日志格式是个容易被忽略的坑。你在终端里看日志觉得挺清楚,但到了日志平台里一搜,乱七八糟的格式根本没法解析。我在项目中遇到过两次这种情况,折腾了两天才把历史日志洗干净。血的教训。

现在业界主流是结构化日志,说白了就是用 JSON 或其他结构化格式来记录。每条日志都是一个结构体,字段清晰,解析方便。

一个标准的 JSON 格式日志长这样:

{
  "timestamp": "2025-04-07T10:23:45.123+08:00",
  "level": "ERROR",
  "logger": "com.example.order.OrderService",
  "trace_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "user_id": "9527",
  "message": "订单支付超时",
  "duration_ms": 3050,
  "extra": {
    "order_id": "ORD20250407001",
    "retry_count": 3
  }
}

对比一下传统文本格式和结构化格式:

对比维度 结构化日志(JSON) 非结构化日志(文本)
机器可解析性 高,直接按字段查询 低,需要用正则硬抠
人类可读性 中等,紧凑但清晰 高,自然语言风格
查询效率 高,索引友好 低,全文本扫描
存储空间 相对较大 相对较小
兼容性 主流日志平台均支持 需要定制解析器

我的建议很简单:只要你的日志要进平台、要做分析,一律用结构化格式。别图省事写纯文本,后面有你哭的时候。

重点字段必须包含:timestamp(带时区)、level、logger 名称、trace_id(链路追踪用)、message(核心描述)。如果有业务上下文,用 extra 字段兜着,不要塞在 message 里。

2.3 日志存储 — 别让日志撑爆磁盘

日志不存不行,存太多也不行。你想想看,一个高并发的服务,一天能产生几十 GB 日志。如果不做控制,磁盘说爆就爆。我曾经接手过一个项目,日志没设轮转,半年没清理,最后磁盘满了,服务全挂。嗯,这个教训很深刻。

日志存储的核心策略就三个词:轮转、压缩、清理。

轮转策略:

  • 按大小轮转:单个日志文件达到阈值(比如 100MB)就切分。适合流量稳定的服务。
  • 按时间轮转:每小时或每天生成一个新文件。适合按天排查问题的场景。
  • 混合策略:两者结合,哪个先触发就切。我个人最推荐这种方式。

下面是一个 Python logging 的轮转配置,我常用的模板:

import logging
from logging.handlers import RotatingFileHandler

handler = RotatingFileHandler(
    "app.log",
    maxBytes=100 * 1024 * 1024,  # 100MB
    backupCount=10                # 保留最近10个文件
)

logging.basicConfig(
    level=logging.WARN,
    handlers=[handler],
    format='%(asctime)s [%(levelname)s] %(name)s: %(message)s'
)

压缩与归档:轮转出来的旧日志别直接扔。用 gzip 压缩一下,体积能缩小到原来的十分之一。很多日志框架自带压缩功能,记得打开。

保留策略:定好保留周期。一般业务日志保留 30 天,安全审计日志保留 6 个月以上。别不舍得删,存太多没用,反而拖慢检索速度。

避坑指南:我曾经在配置日志轮转时把 backupCount 设成了 0,结果轮转直接删旧文件,不留备份。排查问题需要回溯日志时才发现早被清掉了。backupCount 最少设 3,重要系统设 10 以上。

2.4 从运维角度看日志基础

明白级别、格式、存储这三大基础之后,你再看日志巡检规则,思路就清晰了。级别帮你过滤噪音,格式让规则能精准匹配,存储保证你有足够的数据可查。三者配合,才能写出既高效又可靠的巡检规则。

最后说一句心里话:日志规范越早定越好。等项目跑起来再回头改,成本太高了。我建议你在项目第一天就把级别标准、JSON 模板、轮转策略写在文档里。后面省下的时间,比你想象的多得多。

实践清单:
✅ 确定每个级别的使用边界
✅ 统一使用结构化 JSON 格式
✅ 字段名用小写加下划线(snake_case)
✅ 设置混合轮转策略(100MB + 每天)
✅ 压缩历史日志,保留至少 15 天
✅ 运行时支持动态调整日志级别