良好的日志是运维、开发人员排查问题的好工具,本文倡议定义 JSON 格局的结构化日志格局,从而无效优化人工以及机器排查日志的效力,并能不便创立机器索引。原文: The Art of Logging
从历史上看,日志对于诊断应用程序和基础设施性能十分重要,被广泛应用于业务仪表板的可视化和性能剖析。
对日志文件中的数据进行结构化,以便可能无效提取、操作和剖析数据 (除了便于人类了解,也便于机器剖析) 的重要性正在迅速回升。此外,微服务的衰亡也带来了另一个挑战,即怎么在整个零碎中跟踪申请的流传。
本文将介绍便于人和机器解析、了解的日志构造的最佳格局,特地是跟用户登录无关的要害信息及数据结构的倡议,并将尝试提供一些重要的注意事项。
为什么日志应该是人类可读的?
只管日志最后是由机器来解析、解决和存储的,但当初正越来越多的由人类来读取、了解和诊断。日志是咱们考察凶杀现场的最佳指标,而凶手正是咱们的死敌: Bug!🐛
没什么比试图了解简短而且非结构化的日志线中失落的信息更令人丧气和耗时的了。日志必须有有意义,并且人们应该能够很容易了解和深刻开掘与他们无关的内容。
66.249.65.159 - - [06/Nov/2014:19:10:38 +0000] "GET /news/53f8d72920ba2744fe873ebc.html HTTP/1.1" 404 177 "-" "Debian APT-HTTP/1.3 (0.8.16~exp12ubuntu10.16)"
只管咱们曾经习惯了默认的 Nginx 格局,但下面的示例依然很难浏览和解决。例如,这是为了再现生产 bug 而提取的微小日志文件的一部分,很难了解其背地含意是什么。
JSON 绝对于其余数据交换格局 (如 XML) 的劣势非常明显,这是一种在数组中有序嵌套的键值对的简略语法,对人类来说很容易读、写和了解。
那么,用 JSON 编写的日志音讯是什么样子的呢?以下是与之前雷同的 JSON 格局的 Nginx web 服务器日志示例:
{
"time": "06/May/2022:19:10:38 +0100",
"remote_ip": "66.249.65.159",
"remote_user": "-",
"request": "GET /news/53f8d72920ba2744fe873ebc.html HTTP/1.1",
"response": 404,
"bytes": 177,
"referrer": "-",
"agent": "Debian APT-HTTP/1.3 (0.8.16~exp12ubuntu10.16)"
}
为什么日志应该是对机器敌对的?
再次思考下面的日志线示例:
66.249.65.159 - - [06/Nov/2014:19:10:38 +0000] "GET /news/53f8d72920ba2744fe873ebc.html HTTP/1.1" 404 177 "-" "Debian APT-HTTP/1.3 (0.8.16~exp12ubuntu10.16)"
为了了解,咱们须要:
- 了解语法
- 编写逻辑来解析音讯并提取须要的数据
可怜的是,这种逻辑很软弱,如果日志格局产生了更改(比方开发人员增加了一个新字段或更改了字段程序),那么解析器就会解体,置信任何人都有面对或经验相似问题的时候。
而这就是像 JSON 这样的结构化格局能够提供帮忙的中央。键值对使提取特定值和跨数据集筛选和搜寻变得容易,如果增加了新的键值对,解析日志音讯的软件将只是疏忽那些非冀望的键,而不会齐全生效。
在机器上应用 JSON 日志的益处是:
- 具备结构化的格局,因而便于剖析日志和查问每个字段。
- 每种编程语言都能够对其进行解析。
通常,咱们能够在日志解析零碎 (ELK、newRelic、Datadog 等) 中聚合 JSON 数据,从而为咱们提供弱小的报告、搜寻和对数据的洞察能力。这些工具使索引某些字段变得更容易,从而解决在微服务环境下跟踪申请的问题。
应该蕴含哪些信息?
这里列举了应该蕴含在日志中的信息列表,有些元素是可选的,字段名后面的 (o) 示意可选字段。
message <string>
: 用于形容状况的人类可读的信息,在过滤时易于浏览,以取得对内容的概述。level <integer>
: 优先级级别的数值示意(下一节将具体介绍),对于将音讯按不同优先级排序或生成蕴含零碎概述的仪表板十分有用。level_name <string>
: 优先级级别的字符串示意(更多细节将在下一节中介绍)。datetime_iso <DateTime>
: iso8601 格局的日期,因为咱们须要将工夫与其余事件相关联,因而是必填项。只管能够应用服务器的日期 - 工夫,但可能会产生误导,因为服务器的工夫可能并不统一,甚至可能位于不同的时区。correlation_id <string(uuidv4)>
: 这是微服务环境的一个重要字段,咱们将基于解析后的音讯 / 申请的 correlation id 来跟踪服务之间整个链路的申请。- (o)
hostname <string>
: 用于确定是哪台机器生成了此日志,倡议在微服务环境中应用。当服务器日志曾经从 docker 的服务名映射到原始主机时,可能是多余的。 - (o)
build_id <string>
: 记录信息的软件版本,能够帮忙跟踪不兼容问题,特地是那些在服务器端软件部署期间产生的问题。 - (o)
application<string>
: 用于辨认哪个设施或应用程序生成了此日志。 - (o)
owner_id <string(uuidv4)/null>
: 报告用户 id 或 API key id(如果有的话),能够追踪用户执行了哪些步骤来再现他的操作。 - (o)
tenant_id <string(uuidv4)/null>
: 报告可用的租户 id,对于多租户零碎十分有用。 - (o)
tags <string[]>
: 能够是一个元素数组,蕴含对于申请的元信息,如类型、应用的协定等。 - (o)
stacktrace: <string/null>
: 有 stack trace 时以字符串格局显示 stack trace。 - (o)
exception: <string/null>
: 有异样音讯时显示异样音讯。
日志级别和相干日志码
<style> table th:first-of-type {width: 100px;} </style>
日志级别 | 日志码 | 形容 |
---|---|---|
Debug | 100 | 具体的调试信息。 |
Info | 200 | 感兴趣的事件。例如: 用户登录或 SQL 日志。 |
Notice | 250 | 失常但重要的事件。 |
Warning | 300 | 不是谬误的异样事件。示例: 应用已弃用的 API; API 使用不当。 |
Error | 400 | 不须要立刻解决的运行时谬误,但通常应该记录和监控。 |
Critical | 500 | 重大事件。示例: 利用组件不可用; 意想不到的异样。 |
Alert | 550 | 必须立刻采取行动。例如: 整个网站瘫痪。应该会触发 SMS 告警。 |
Emergency | 600 | 紧急情况: 零碎不可用。 |
倡议格局
那么,用 JSON 编写的日志音讯是什么样的呢?
以下是示例倡议的日志概念格局:
察看
- 在日志服务器中,应该为以下元素建设索引,以便更快搜寻:
owner_id
、tenant_id
、correlation_id
、level
、level_name
和application
。 - 当可选字段可用时,应该增加到日志中,只能在没有的时候将其疏忽,而在调试零碎时,它们的值将是可见的。
- context 元素能够蕴含其余有用的字段(比方传入申请的打印)。
- 出于安全性或合规性起因 (个人信息爱护),日志应该对申请中可能呈现的关键字段(比方明码) 设置一些过滤器,以便在输入内容之前匿名化。
- 每个服务都应该转发收到的
correlation_id
,如果这个值不存在,应该生成一个新值并将其传递给下一个服务。API 网关(如果有的话) 应该始终关注该字段是否存在、是否须要生成。
最佳实际
- 花工夫设计日志构造,使格局满足咱们的须要,并且能够很容易复制。然而,有些团队可能须要不同的版本,还要思考适宜需要的粒度级别。通常,公司外部的 ” 日志概念 ” 文档能够让所有团队遵循同一种模式,并且有新的开发人员退出时会十分有用。
- 尽可能多的记录日志。在产生致命异样时晓得模块和行号,或者在遇到安全漏洞时晓得 IP/ 用户名,对于更快、更精确解决问题是十分贵重的。如果想防止一些不必要的乐音,依然能够调整级别,通过教训能够晓得什么级别最适宜以后我的项目!
- 放弃一致性是每个人的首要任务。JSON 音讯中适当的键和精确的值使调试更容易、更无效。Correlation Id 和日志级别能够明确证实这一点。
- 编写代码的同时记录日志,像编写单元测试一样,尝试放弃雷同的格调并记录零碎交互。为了防止失落函数的上下文和边缘状况,当场实现比稍后增加更容易。
最初
- 本文不是要推动规范,而是要尝试创立一种逻辑化组织的日志格局,以优化如 newRelic 或 ELK 等日志解析零碎。这一格局将帮忙咱们生成有用的仪表板、指标和事件告诉(例如,在谬误百分比超过 5% 时触发警报)。
- 在应用程序中实现标准化日志零碎将破费肯定的工夫和金钱,调试也须要付出代价,特地是无关要害边界条件信息的状况下。在做出决定的时候应该衡量思考。
- 日志记录是一个公说公有理、婆说婆有理的话题,有时还会引起一致。然而,无论应用哪种格局,总是比齐全不必日志要好。
- 倡议应用异步日志记录来防止性能问题。
* 你好,我是俞凡,在 Motorola 做过研发,当初在 Mavenir 做技术工作,对通信、网络、后端架构、云原生、DevOps、CICD、区块链、AI 等技术始终保持着浓重的趣味,平时喜爱浏览、思考,置信继续学习、一生成长,欢送一起交流学习。\
微信公众号:DeepNoMind*
本文由 mdnice 多平台公布