日志的艺术

本文涉及的产品
全局流量管理 GTM,标准版 1个月
日志服务 SLS,月写入数据量 50GB 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: 日志的艺术

良好的日志是运维、开发人员排查问题的好工具,本文建议定义 JSON 格式的结构化日志格式,从而有效优化人工以及机器排查日志的效能,并能方便创建机器索引。原文: The Art of Logging


image.png

从历史上看,日志对于诊断应用程序和基础设施性能非常重要,被广泛应用于业务仪表板的可视化和性能分析。


对日志文件中的数据进行结构化,以便能够有效提取、操作和分析数据(除了便于人类理解,也便于机器分析)的重要性正在迅速上升。此外,微服务的兴起也带来了另一个挑战,即怎样在整个系统中跟踪请求的传播。


本文将介绍便于人和机器解析、理解的日志结构的最佳格式,特别是跟用户登录有关的关键信息及数据结构的建议,并将尝试提供一些重要的注意事项。


为什么日志应该是人类可读的?


尽管日志最初是由机器来解析、处理和存储的,但现在正越来越多的由人类来读取、理解和诊断。日志是我们调查凶杀现场的最佳指标,而凶手正是我们的死敌: Bug!🐛


image.png

没什么比试图理解冗长而且非结构化的日志线中丢失的信息更令人沮丧和耗时的了。日志必须有有意义,并且人们应该可以很容易理解和深入挖掘与他们有关的内容。


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 这样的结构化格式可以提供帮助的地方。键值对使提取特定值和跨数据集筛选和搜索变得容易,如果添加了新的键值对,解析日志消息的软件将只是忽略那些非期望的键,而不会完全失效。

image.png

Alex Knight@Unsplash


在机器上使用 JSON 日志的好处是:


  • 具有结构化的格式,因此便于分析日志和查询每个字段。
  • 每种编程语言都可以对其进行解析。


通常,我们可以在日志解析系统(ELK、newRelic、Datadog 等)中聚合 JSON 数据,从而为我们提供强大的报告、搜索和对数据的洞察能力。这些工具使索引某些字段变得更容易,从而解决在微服务环境下跟踪请求的问题。


应该包含哪些信息?


这里列举了应该包含在日志中的信息列表,有些元素是可选的,字段名前面的(o)表示可选字段。


  • message : 用于描述情况的人类可读的信息,在过滤时易于阅读,以获得对内容的概述。
  • level : 优先级级别的数值表示(下一节将详细介绍),对于将消息按不同优先级排序或生成包含系统概述的仪表板非常有用。
  • level_name : 优先级级别的字符串表示(更多细节将在下一节中介绍)。
  • datetime_iso : iso8601格式的日期,因为我们需要将时间与其他事件相关联,因此是必填项。尽管可以使用服务器的日期-时间,但可能会产生误导,因为服务器的时间可能并不一致,甚至可能位于不同的时区。
  • correlation_id : 这是微服务环境的一个重要字段,我们将基于解析后的消息/请求的 correlation id 来跟踪服务之间整个链路的请求。
  • (o)hostname : 用于确定是哪台机器生成了此日志,建议在微服务环境中使用。当服务器日志已经从 docker 的服务名映射到原始主机时,可能是多余的。
  • (o)build_id : 记录信息的软件版本,可以帮助跟踪不兼容问题,特别是那些在服务器端软件部署期间发生的问题。
  • (o)application: 用于识别哪个设备或应用程序生成了此日志。
  • (o)owner_id : 报告用户 id 或 API key id(如果有的话),可以追踪用户执行了哪些步骤来再现他的操作。
  • (o)tenant_id : 报告可用的租户 id,对于多租户系统非常有用。
  • (o)tags : 可以是一个元素数组,包含关于请求的元信息,如类型、使用的协议等。
  • (o)stacktrace: : 有 stack trace 时以字符串格式显示 stack trace。
  • (o)exception: : 有异常消息时显示异常消息。


日志级别和相关日志码


image.png


建议格式


那么,用 JSON 编写的日志消息是什么样的呢?


以下是示例建议的日志概念格式:


image.png

使用 carbon 生成的示例消息


观察


  • 在日志服务器中,应该为以下元素建立索引,以便更快搜索: owner_idtenant_idcorrelation_idlevellevel_nameapplication
  • 当可选字段可用时,应该添加到日志中,只能在没有的时候将其忽略,而在调试系统时,它们的值将是可见的。
  • context 元素可以包含其他有用的字段(比如传入请求的打印)。
  • 出于安全性或合规性原因(个人信息保护),日志应该对请求中可能出现的关键字段(比如密码)设置一些过滤器,以便在输出内容之前匿名化。
  • 每个服务都应该转发收到的correlation_id,如果这个值不存在,应该生成一个新值并将其传递给下一个服务。API 网关(如果有的话)应该始终关注该字段是否存在、是否需要生成。


最佳实践


  • 花时间设计日志结构,使格式满足我们的需要,并且可以很容易复制。然而,有些团队可能需要不同的版本,还要考虑适合需求的粒度级别。通常,公司内部的"日志概念"文档可以让所有团队遵循同一种模式,并且有新的开发人员加入时会非常有用。
  • 尽可能多的记录日志。在发生致命异常时知道模块和行号,或者在遇到安全漏洞时知道 IP/用户名,对于更快、更准确解决问题是非常宝贵的。如果想避免一些不必要的噪音,仍然可以调整级别,通过经验可以知道什么级别最适合当前项目!
  • 保持一致性是每个人的首要任务。JSON 消息中适当的键和准确的值使调试更容易、更有效。Correlation Id 和日志级别可以明确证明这一点。
  • 编写代码的同时记录日志,像编写单元测试一样,尝试保持相同的风格并记录系统交互。为了避免丢失函数的上下文和边缘情况,当场完成比稍后添加更容易。


最后


  • 本文不是要推动标准,而是要尝试创建一种逻辑化组织的日志格式,以优化如 newRelic 或 ELK 等日志解析系统。这一格式将帮助我们生成有用的仪表板、指标和事件通知(例如,在错误百分比超过 5%时触发警报)。
  • 在应用程序中实现标准化日志系统将花费一定的时间和金钱,调试也需要付出代价,特别是有关关键边界条件信息的情况下。在做出决定的时候应该权衡考虑。
  • 日志记录是一个公说公有理、婆说婆有理的话题,有时还会引起分歧。但是,无论使用哪种格式,总是比完全不用日志要好。
  • 建议使用异步日志记录来避免性能问题。


相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
目录
相关文章
|
5月前
|
自然语言处理 前端开发 数据可视化
1024程序员节:合合信息“百宝箱”开启智能文档处理新纪元
在数字化转型这股大洪流中,文档处理已然成为企业和开发者日常作业中的一块重要基石。合合信息给开发者送了个大礼——智能文档处理“百宝箱”。这“百宝箱”里头,啥都有,全面、高效、准确,简直就是文档处理的超级神器。他们想通过这个产品,让技术不再那么高不可攀,让更多人,特别是咱们开发者,能轻轻松松地把文档处理的能力加到自己的工作中去。下面来详细看一下吧~
101 0
代码之外的艺术:技术写作的深度与温度
在数字时代的浪潮中,技术写作往往被视作一种冷冰冰的信息传递方式。然而,当我们深入探究时,便会发现它其实是一种富有创造力的艺术形式。本文将通过个人的技术感悟来探讨如何赋予技术写作以深度和温度,使其不仅仅是代码和逻辑的简单堆砌,而是一种能够触动人心、引发思考的创作活动。
|
10月前
|
前端开发 JavaScript 算法
前端色彩艺术:深入解析与实战指南
前端色彩艺术:深入解析与实战指南
308 1
|
10月前
|
SQL 存储 监控
日志问题精要:分析与总结
该文档讲述了应用系统日志记录的重要性和规则。主要目的是记录操作轨迹、监控系统状态和回溯故障。日志记录点包括系统入口、调用其他模块、调用结束、出口和出错时。内容应遵循UTF-8编码,避免敏感信息,按INFO级别记录,及时、完整且安全。日志输出要控制频率和长度,不影响系统性能,并按策略备份和清理。日志等级分为DEBUG、INFO、WARN、ERROR和FATAL。日志文件应有明确目录结构,大小有限制,并定期清理。注意事项包括输出异常堆栈、避免打印对象实例的hashCode、选择合适的日志框架和格式,并支持动态修改日志级别。还要实现链路追踪,确保在多线程环境中正确记录日志。
116 0
|
10月前
|
人工智能 算法 数据挖掘
ChatGPT 调教日记(二):程序员转量化的背景知识
ChatGPT 调教日记(二):程序员转量化的背景知识
92 0
持续输出:自媒体持续输出文字内容、视音频创作(视频课程、书籍章节)
持续输出:自媒体持续输出文字内容、视音频创作(视频课程、书籍章节)
|
Cloud Native Go
如何在面试中展示你的创造性
如何在面试中展示你的创造性
77 0
|
10月前
|
消息中间件 运维 数据可视化
《小丁日志历险记》
一年前,小丁加入了一家初创公司,准备大干一番刚加入公司,业务规模小,使用少量云主机就可以满足需求了最初,业务刚上线,问题比较多;小丁通过ssh+grep的方法,有效抓住了大部分初期的bug,简单高效过了一段时间,公司的业务获得了巨大成功,一开始的那些机器数,快顶不住压力了幸好小丁的公司使用了云服务,...
《小丁日志历险记》
如何用ChatGPT做书籍、报告、文件的读取与互动式问答?故事人物活起来
该场景对应的关键词库(15个): 书籍、报告、文件、详细信息、查询、主题、作者、出版日期、出版社、问题、方面、原则、方法、概括、主要观点、解释。
221 0
|
机器学习/深度学习 人工智能 自然语言处理
AI模型教你写出秒抓读者眼球的好标题
广告大师大卫·奥格威曾在《一个广告人的自白》中提到:标题在大部分广告中,都是最重要的元素,能够决定读者会不会看这则广告。一般来说,读标题的人比读内人的人多出4倍。换句话说,你所写标题的价值将是整个广告预算的80%。因此对于一篇文章、新闻来说,标题的好坏决定了点击和流量。本文介绍通过ModelScope的AI模型PALM来完成标题/摘要生成
AI模型教你写出秒抓读者眼球的好标题