怎么记日志才算专业,SRE、DEV 都应该了解的实践指南

本文从日志目的、上下文、结构化、指标与追踪分工、日志级别和采集过滤几个方面,说明怎样把日志从无用流水账变成可用于排障、关联分析和成本控制的可观测证据。

作者 Mike Shi

核心要点

  • 专业日志不是“记录一切”,而是只记录未来排障、理解系统状态和判断业务影响时真正会用到的证据。
  • 日志必须带上下文,至少能关联请求、用户、操作、输入状态以及 OpenTelemetry 中的 trace ID、span ID。
  • 结构化日志比自由文本更适合查询、聚合、可视化和成本控制,也更容易和指标、追踪数据关联。
  • 日志、指标和 Trace 有不同分工:高频重复信号应转成指标,因果链路应进入 Trace,日志负责保留关键上下文和事件细节。

坦白说:很多日志都只是无用信息…

[INFO] Starting process … probably.
[DEBUG] Made it to line 42 — still alive.
[TRACE] Function entered. Leaving soon.
[INFO] User clicked a button. Which one? No idea.
[WARN] Everything’s fine, just felt like warning you.
[DEBUG] Variable x = 7. Might change. Might not.
[INFO] Operation completed successfully (we think).
[TRACE] Loop iteration #12 of infinite sadness.
[DEBUG] Placeholder for meaningful message.
[INFO] Shutting down gracefully … except when not.

作为开发人员,我们常常像撒彩纸一样随意记录日志 —— 每个函数的入口、每个变量、每一次系统 “心跳” 都不放过。没过多久,数太字节的无意义日志行就会堆积如山,填满那些没人看的仪表盘。

我们向可观测性供应商支付数百万美元,却只是为了存储这些 “垃圾”。每一条无用的日志行都在消耗计算资源、磁盘空间和资金。没有明确目的的日志记录不是可观测性实践,而是 “乱扔垃圾”。

即便现在的可观测性平台借助列式存储大幅提升了压缩效率,也没有理由记录所有内容。这种无差别记录仍会让根本原因分析变成 “大海捞针”—— 稀释你真正需要的有效信号,而且你还得为此支付更高成本。

我们需要有选择性地记录日志:只记录那些有助于理解系统、调试实际问题或说明业务影响的信息,其他无关内容都不必记录。

日志记录的核心原则

每一条日志记录都是一个主动选择,而非下意识的操作。如果这条日志无法帮未来的你在凌晨 3 点排查出 bug,那就删掉它。日志记录不是记日记,要做到简洁、清晰且真正有用。

在敲下 logger.info(信息级日志记录代码)之前,先停下来问问自己:我之后真的会用 grep(一种文本搜索工具)查找这条日志吗?

如果答案是否定的,就删掉它。日志不是叙事流水账,而是证据。它们的存在,是为了在系统出现问题时,告诉你当时系统的运行状态。

日志不应被排在可观测性实践的末尾。它们不只是用于验证问题的 “显微镜”,更是用于发现问题的 “地图”。有时候,获取洞见最快的方式,就是直接探索原始文本 —— 通过 grep 搜索、筛选,跟着直觉去挖掘。

日志能激发探索欲:它们能展现出指标可能掩盖的细微差别,以及追踪数据无法传递的上下文信息。不要把日志当作最后的求助手段,而应将其视为 “实时输出的真相来源”,从一开始就主动去探索。

判断问题 如果答案是否定的 更合适的处理方式
这条日志能帮助定位真实故障吗? 不要记录 删除或降级为开发期调试信息
未来能用字段检索到它吗? 先补结构化字段 增加请求 ID、用户 ID、操作名、状态码等上下文
它是否高频重复出现? 不要逐条存储 转成指标或采样日志
它是否包含敏感信息? 不要直接写入 脱敏、过滤或只保留安全摘要

无上下文,不日志

只写 “发生错误”,却不包含输入数据、ID 或系统状态,这样的日志毫无意义。要添加足够的上下文信息,以便还原当时的场景 —— 比如请求 ID、用户 ID、输入参数、操作名称等。如今,借助 OpenTelemetry(一种开源可观测性框架),你可以免费获取追踪 ID(trace ID)和跨度 ID(span ID),一定要善用它们。通过追踪 ID 与追踪数据(甚至指标)关联起来的日志,其价值远胜于孤立的文本行。

日志不是可观测性实践中独立的一环,而是根本原因分析的 “收尾章节”。你通过指标触发告警,通过追踪数据展开调查,然后再查看日志,了解到底发生了什么。当日志通过追踪 ID 和跨度 ID 关联起来后,它们就不再是无用信息,而成为了精准、有上下文的证据 —— 直接与单个请求的路径相关联。这才是有明确目的的可观测性实践,而非一堆杂乱无章的文本。

结构化日志,而非自由文本

自由文本形式的日志早已过时。结构化日志(无论是 JSON、CSV 格式,还是键值对形式)不仅更易于查询,更是数据分析的基础。一旦日志具备了结构化格式,规律便会自然浮现

  • “这个错误从上周开始激增。”
  • “这个问题大多在事件 X 之后出现。”
  • “这个警告与某次特定部署相关。”

日志的未来发展方向,不是逐行阅读单条日志,而是从成千上万条日志中发现整体规律。

图片来自网络

结构化日志让图表展示变得简单高效。虽然很多可观测性平台支持 “读取时解析 schema”(schema on read),但这种灵活性是有代价的:每一次查询,系统都要逐行扫描并解析原始文本,推断出本该从一开始就存在的结构化格式。这类查询计算成本高、速度慢,而且用户编写查询语句也更困难。

预先结构化的日志则能彻底扭转这种低效局面。当你的数据本身就具备结构化格式时,就可以充分利用列式存储和原生聚合功能 —— 在毫秒级时间内完成事件的查询、可视化和关联分析,而无需等待数分钟。

明确何时该统计度量,而非一味记录日志

并非所有事件都适合写入日志流。有些信息需要更规范的结构和时间维度记录 —— 这正是跨度(span)和指标(metric)的用途。如果你要统计延迟时间、用户流程或分布式系统中的因果关系,就应该生成跨度数据而非日志。跨度能捕捉耗时、上下文以及服务间的关联关系,告诉你 “为什么某个操作变慢或出错”;而日志只能告诉你 “某个问题发生了”。

同样的逻辑也适用于指标:将重复出现的日志转化为可告警、可高效聚合的有效信号。如果你发现自己每秒都在记录数百条相同的日志信息,那你就不是在进行可观测性实践,只是在浪费存储资源。对这类信息,只需统计一次、进行汇总,然后让指标和追踪数据来承担主要的分析工作即可。

日志级别是给人看的,而非给机器看的

日志记录不是个人的调试日记,而是留给未来团队成员的共享资料。每一条日志都应能让他人清晰理解当时发生了什么,无需猜测你的意图。记录日志时,要为下一次故障排查做准备,而非受当下情绪影响。你的日志记录着系统的运行历程,要让这段 “历程” 值得一读。例如:

  • 错误(ERROR):需要人员介入处理。系统出现故障。
  • 警告(WARN):出现意外情况,但系统可正常运行。后续需调查。
  • 信息(INFO):系统的常规运行状态,有记录价值。
  • 调试 / 追踪(DEBUG/TRACE):开发人员临时用于排查问题的信息 —— 不应轻易提交到生产环境。

日志记录要审慎。除非确实需要采取行动,否则不要将某条日志标记为 “错误” 级别。滥用 “错误” 级别会让告警机制失去敏感度,导致团队对真正重要的问题视而不见。每个日志级别都应传递明确的意图:哪些问题需要立即修复,哪些需要持续关注,哪些可以忽略。

不过,追踪级日志也有其用武之地。例如,在 ClickHouse Cloud(一款云原生数据库)的后台运行中,我们会大量使用追踪级日志,帮助工程师排查性能问题,并为大规模用户提供支持。这是一种经过深思熟虑的例外情况 —— 当你运营着一个实时为数千个工作负载提供服务的分布式数据库时,这种日志级别是必要的。但对于大多数应用而言,如此详细的日志记录并非可观测性实践,只是在制造无用信息。

日志级别 应表达的含义 常见误用
ERROR 需要人员介入,系统或关键流程已经失败 把所有异常分支都标成错误
WARN 出现非预期情况,但系统还能继续运行 用警告表达开发者的不确定感
INFO 关键状态变化、业务事件或有长期排查价值的信息 记录每一步无意义流程
DEBUG / TRACE 开发或特定生产排障场景下的细粒度信息 长期开启并写入大规模生产流量

助力高效日志记录的工具

现在已有丰富的软件开发工具包(SDK)和强大的过滤工具,无需再 “无差别记录所有日志”,要善用这些工具。

现代的 OpenTelemetry Collector SDK(收集器软件开发工具包)能让你精准控制日志记录内容:你可以对代码进行埋点配置,只生成有意义的日志行,然后在数据摄入或收集阶段过滤或丢弃所有无关日志。

例如:

  • 过滤处理器(filter processor)支持使用 OpenTelemetry 转换语言(OTTL),根据日志的严重级别、资源属性或内容模式等条件,丢弃不需要的日志、指标或追踪数据。
  • 如果你的可观测性平台支持,还可以在代理(agent)、收集器网关(collector gateway)或数据摄入阶段进行过滤,确保无用日志不会被写入、存储或建立索引 —— 从而节省计算资源、存储成本和查询成本。
  • 如果管理员发现有用户在生成无用日志,可以在数据处理流程中强力过滤这些日志,或者强制推行 “最小日志记录” 策略。即便你使用的是专有平台,它们通常也会提供类似的过滤或摄入控制工具,只是可能不会公开宣传这些功能。

有目的地面向日志,否则不如不记录

可观测性的关键不在于数据量,而在于清晰度。每一条日志都应凭借其独特价值占据一席之地 —— 即解释那些指标和追踪数据无法传递的信息。没有明确目的的日志记录,只会浪费资金,并掩盖有价值的洞见。

日志记录要审慎,要采用结构化格式,要添加上下文信息,要明确何时该统计度量、何时该进行追踪、何时该保持 “沉默”。现代工具让规范的日志记录变得比以往更简单,但最终的自律仍需来自你自身。

归根结底,出色的日志记录并非要捕捉所有发生的事情,而是要捕捉关键信息。

FAQ

Q1:什么时候应该写日志,什么时候应该写指标?

如果信息用于解释某个具体事件、请求或状态变化,适合写日志;如果信息是高频重复、需要聚合、告警或看趋势,通常应该转成指标。

Q2:结构化日志一定要用 JSON 吗?

不一定。JSON、CSV、键值对都可以,关键是字段含义稳定、可解析、可聚合,并且能被日志平台直接查询。

Q3:生产环境能不能开 DEBUG 或 TRACE?

可以,但应当有明确场景、范围、采样或过滤策略。长期无差别开启 DEBUG/TRACE 会放大成本,并稀释真正有用的信号。

原文链接:https://thenewstack.io/when-to-log-and-when-to-shut-up/

延伸路径

继续看解决方案和产品对比

如果你正在做监控、可观测性或故障定位相关选型,建议从解决方案和产品对比继续往下看。

快猫星云 联系方式 快猫星云 联系方式
快猫星云 联系方式
快猫星云 联系方式
快猫星云 联系方式
快猫星云