NEE's Blog

日志消息是为运维人员写的

March 08, 2026

本文翻译自 Log messages are mostly for the people operating your software,原载于 Hacker News。

日志的真正受众

最近我读了 Evan Hahn 的《The two kinds of error》,其中顺便提到了日志的话题,这引发了我的思考。我之前写过一篇关于系统管理员视角下错误日志级别含义的文章,但那篇文章遗漏了日志消息的一个根本问题:在大多数情况下,日志消息是为运维你软件的人写的

当你准备添加一条非调试级别的日志消息时,应该问自己的问题之一是:运行你程序的人能从这条消息中得到什么?

开发者的陷阱

根据我的经验,开发者很容易写出给自己看的日志消息。这些消息对调试很有用,可以帮助追踪程序状态,而且因为你沉浸在程序中,拥有所有上下文,这样写消息感觉很自然。

这个问题在不常见的错误消息上尤其严重——我学会了让这类消息尽可能详细。类似的原则也适用于不常记录的日志消息。

但如果你的软件成功了(尤其是分发给其他人使用),大多数运行它的人不是开发者,他们只是运维人员

这甚至可能包括未来的你自己——当你几个月没碰过这段代码的时候。

日志应该对运维人员有意义

如果你希望日志消息在”帮我诊断这个问题”的邮件之外还有用,它们就必须对运维软件的人有意义。

这并不意味着”只报告他们能修复和需要修复的错误”——虽然这也是一部分。更重要的是,通过日志提供的信息应该是运维人员能够理解和使用的,而不需要什么魔法解码器(magic decoder ring)。

如果运维你软件的人看到某条日志消息后什么都得不到,那你可能根本不应该默认记录它(或者你需要重新措辞,让人能从中得到有用的信息)。

在 Evan Hahn 的术语中,这适用于”预期错误”和”意外错误”两类日志消息。当然,如果程序要终止,一定要告诉系统管理员原因。

系统管理员的视角

从系统管理员的角度来看,关于预期错误的日志消息让我们能够诊断是什么出了问题导致某件事失败。我们对此的关注程度部分取决于这类错误的频率。

然而,频率不是唯一因素。以邮件传输代理(MTA)为例,它们通常会有相对详细的邮件处理日志,会记录每一个预期错误——比如”无法进行 DNS 查询”或”无法连接到远程机器”——即使这些错误可能经常发生。

这非常有用,因为我们有时非常关心某封特定邮件发生了什么。

我的思考

这篇文章让我想起了一些实际项目中的经历:

  1. “神秘代码”问题:很多日志消息充满了内部变量名、缩写,只有原开发者能看懂。比如 Error: foo.bar is null —— 对运维人员来说,这毫无意义。

  2. 信息过载:有些系统默认输出大量调试级别的日志,淹没了真正重要的信息。如果 99% 的日志对运维人员没用,它们就成了噪音。

  3. 可操作的日志:好的日志应该回答”发生了什么”和”我能做什么”。比如 Connection to database 'users' failed after 3 retries. Check if PostgreSQL is running on db.example.com:5432 就比 DB error: timeout 有用得多。

  4. 结构化日志:现代实践推荐使用结构化日志(JSON 格式),这样既便于人类阅读(配合工具),也便于机器解析和告警系统使用。

核心要点

  1. 日志的受众是运维人员:他们可能不了解代码细节,需要清晰、有上下文的消息。

  2. 避免”只有我能看懂”的日志:如果你写的日志需要翻代码才能理解,那它对运维人员就没用。

  3. 默认只记录有价值的消息:如果一条消息对运维人员没有实际价值,就不要默认开启它。

  4. 预期错误也需要记录:即使错误是”预期中”的,日志也能帮助运维人员诊断问题根源。

  5. 考虑追踪需求:像邮件系统那样,有时我们需要追踪某个特定请求/消息的完整生命周期。

comments powered by Disqus