4、日志管理基础:日志级别、结构化日志与集中采集

日志这东西,说白了就是数据管道的「黑匣子」。管道跑得好好的,没人会去看日志;一旦出问题,日志就是你唯一的救命稻草。我做了这么多年数据工程,见过太多团队在日志上栽跟头——要么日志太多把磁盘撑爆,要么关键时刻啥都没记下来。

这一章,咱们就把日志管理的基础打扎实。从日志级别怎么选,到结构化日志怎么写,再到日志怎么收上来统一管,一条龙讲清楚。

4.1 日志级别:别什么都记,也别什么都不记

日志级别是个老生常谈的话题,但真用对的人不多。常见的级别就四个:DEBUG、INFO、WARN、ERROR。有些框架还有 TRACE 和 FATAL,但日常够用这四个就行。

级别 含义 生产环境建议 典型场景
DEBUG 调试信息,开发用 关闭 变量值、函数入口/出口、循环次数
INFO 正常流程信息 开启 任务启动、数据量统计、阶段完成
WARN 潜在问题,不影响运行 开启 重试次数超阈值、配置降级、数据延迟
ERROR 明确错误,需要处理 开启 连接失败、数据格式异常、任务中断
我的习惯:开发阶段日志级别开到 DEBUG,上线前统一改成 INFO。但我会留一个「动态调级」的接口——线上出问题时,通过配置中心把某个模块临时切到 DEBUG,问题排查完再切回来。这招比重启服务改配置好用得多。

级别选错了会怎样?我遇到过一件事:有个同事把所有日志都打成了 ERROR,结果告警系统天天响,运维团队直接把它拉黑了。你想想看,满屏都是红色,谁还分得清哪个是真问题?

4.2 结构化日志:让机器能读懂

传统日志长什么样?大概是这样:

2024-01-15 10:23:45 ERROR 连接数据库失败,重试第3次

人眼看得懂,但机器要解析就费劲了。正则写半天,字段还可能漏掉。说白了,这种日志是给人看的,不是给系统用的。

结构化日志就不一样了。它用 JSON 或其他格式把信息组织好,字段清晰,机器直接就能消费。

{
  "timestamp": "2024-01-15T10:23:45.123Z",
  "level": "ERROR",
  "logger": "com.data.pipeline.db.connector",
  "message": "连接数据库失败",
  "retry_count": 3,
  "max_retry": 5,
  "db_host": "prod-db-01.internal",
  "error_code": "DB_CONN_TIMEOUT",
  "duration_ms": 5023
}

看到区别了吗?结构化日志里,每个字段都有明确的含义。查询的时候直接按字段过滤,不用写一堆正则。我在项目里用 Elasticsearch 查日志,level:ERROR AND retry_count:>3 一秒出结果,比 grep 快太多了。

结构化日志的核心字段:
  • timestamp — 时间戳,建议用 ISO 8601 格式带时区
  • level — 日志级别
  • logger — 来源模块或类名
  • message — 人类可读的描述
  • context — 上下文信息(请求ID、任务ID、用户ID等)
  • error — 异常堆栈或错误码(仅ERROR级别)

4.3 日志采集:别让日志烂在机器里

日志写好了,得收上来。不然每台机器上都有一堆文件,查问题的时候挨个 SSH 上去看?那效率太低了。

主流的采集方案就几种:

  • Filebeat / Fluentd — 轻量级采集器,适合容器和虚拟机
  • Logstash — 功能强但吃资源,适合做中间处理
  • Vector — Rust 写的,性能好,配置简单
  • Sidecar 模式 — 每个 Pod 里挂一个采集容器,K8s 环境常用

我个人比较推荐 Vector。原因很简单:它一个二进制就能搞定采集、转换、输出,不像 ELK 那套要搭好几个组件。而且内存占用低,适合在资源紧张的生产环境跑。

我曾经踩过的坑:采集器不要直接写磁盘!有次我把 Filebeat 的输出配成了文件,结果日志写了两份,磁盘三天就满了。正确的做法是采集器只负责读和转发,不落盘。日志的持久化交给后端的存储系统(比如 Elasticsearch 或 S3)去管。

4.4 集中管理:一个地方看所有日志

日志收上来了,得有个地方统一管。常见的组合是 ELK(Elasticsearch + Logstash + Kibana) 或者 EFK(Elasticsearch + Fluentd + Kibana)。最近 Loki 也挺火,轻量,跟 Prometheus 生态配合得好。

集中管理要解决三个问题:

  1. 存储 — 日志量很大,得考虑冷热分层。热数据存 SSD,7 天后移到冷存储,30 天后删掉或归档。
  2. 检索 — 要能按时间、级别、模块、关键词快速过滤。索引设计很重要,字段类型别全用 text。
  3. 权限 — 不是所有人都能看所有日志。开发看 DEBUG,运维看 ERROR,合规审计看全部,得分开。

下面这张图展示了日志从产生到消费的完整链路:

日志管理核心流程 应用服务 数据管道 基础设施 结构化日志 日志采集器 消息队列 Elasticsearch Loki S3 / 冷存储 Kibana / Grafana 告警系统 审计 / 合规 日志从应用产生 → 结构化输出 → 采集转发 → 存储检索 → 消费展示,形成完整闭环

4.5 避坑指南:日志管理常见的五个问题

做了这么多年,我总结了几条日志管理的血泪教训:

  • 别打敏感信息。密码、身份证号、信用卡号,这些不能进日志。我见过有人把 SQL 参数全打出来,里面带着明文密码,结果日志文件被拖库了。
  • 控制日志量。每秒钟几千条 DEBUG 日志,再大的集群也扛不住。设置每秒上限,超过的丢掉或者采样。
  • 统一时间格式。所有服务用 UTC,别有的用北京时间有的用纽约时间。查问题的时候换算时区,能把人逼疯。
  • 日志别当数据库用。有人把业务数据也写进日志,想着反正能查。结果日志系统成了核心存储,日志一挂业务就瘫了。
  • 别忘了日志轮转。不轮转的话,一个日志文件能长到几十 GB,打开都费劲,更别说查问题了。
我曾经遇到过一次严重的生产事故:有个数据管道每天产生 200GB 的日志,但采集器没做限流,直接把 Elasticsearch 集群写爆了。ES 挂了之后,所有依赖 ES 的查询服务也跟着挂了,连锁反应持续了 4 个小时。从那以后,我每条管道上线前都会做日志压力测试,确保采集和存储能扛住峰值。

日志管理看起来简单,但做扎实了不容易。级别选对、结构清晰、采集稳定、存储可靠,这四个点都做到位了,你的数据管道才算有了真正的「可观测性」。下次管道出问题的时候,你会感谢今天认真配日志的自己。