【翻译】结构化日志的价值 - 更好地理解系统

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: 一种比较可行的克服这些困难的方案是以一种一致的、明确的和机器可读的格式来记录系统中最有价值的信息。这种方法称为结构化日志记录。在配套工具的支持下,这些追踪数据有助于更深入地了解你的系统的运行活动,使你能够理解组件之间的相互作用。

1、开篇

正如 Raphael 关于《理解系统》的博文中所述,在复杂系统中隔离和定位错误是一项非常具有挑战的任务。因为功能的实现总是复杂的、分布式的,跨越系统层级的,并且使用了来自许多不同组织架构、不同供应商的设备和技术。

一种比较可行的克服这些困难的方案是以一种一致的、明确的和机器可读的格式来记录系统中最有价值的信息。这种方法称为结构化日志记录。在配套工具的支持下,这些追踪数据有助于更深入地了解你的系统的运行活动,使你能够理解组件之间的相互作用。

相反,当日志仅仅作为纯非结构化文本数据使用时,很难获得任何有用的信息,尤其是在自动化日志分析的场景下。

2、分布式系统中的典型缺点

接下来,我们谈论的是分布式系统中有哪些缺点,为什么它们如此难以被发现?

2.1 接口调用的顺序不对

这是最突出的问题之一,同时也是最难发现的问题类型之一。跟踪它可能会让人很上头,比如这种情况,整个调用流并未按预期顺序来实现,整体功能肯定是无法完全正常工作的,但可能测试的调用居然获得了预期的响应。

2.2 长时间运行的请求

从功能的角度来看,该服务的行为符合预期:只要输入参数调用后就能返回一个有效结果。但是从结果来看,客户却无法完成他的任务,因为服务的响应时间太长了。可能不是你的服务接口引起的,而是调用链中的另一个服务接口。

2.3 冗余调用

在某些情况下,一个服务接口被同一个客户端以相同的参数频繁地调用。这可能是在循环调用接口的情况下作为意外而发生。但也可能是有意为之,因为客户端懒得自己缓存管理状态信息。无论怎样,这都会导致一个非功能性的问题,比如高cpu负载,因为在接口调用的背后可能会有一个巨大的call hierarchy,而这个call hierarchy会被反复触发......

2.4 其他故障

在调用接口时没有满足一些前提条件或后置条件,一个服务被一个未经授权的客户调用,多个客户不能同时得到服务,或者参数值超出范围,都可能会导致更多的故障。当然这里只是列举了一部分故障来源,除此之外还有很多。

但它们都有一个共同点,即如果你还没有记录能贯穿上下文的日志的观念,就很难识别出它们。

3、什么是需要记录的有价值的信息?

首先,需要确定在我们的应用场景中哪些信息是至关重要的,也就是说所有那些帮助我们梳理出软件组件之间是如何相互作用的信息。因为服务接口代表着系统的最前沿,所以肯定要使用结构化日志来记录跟他们相关的信息。

3.1 接口签名

由于我们主要是监控服务接口调用,所以我们需要记录所有的上下文数据,以便能将单条日志明明白白的追溯到是哪个原始接口的调用引发的。
接口签名的日志通常包含了以下名称和/或标识符:

  • 接口
  • 软件组件(实现该接口的)
  • 被调用的方法或函数名
  • 与该方法或函数一起携带的参数

为了使它更容易理解,请想象以下承载我们元数据的json结构。

这个结构是随意的,这里仅是一个示例用于说明目的。在生产代码中,你可以选择任意其他格式,也许还可以编码成流行的协议,如protobuf或message pack。

3.2 通信上下文

其次,我们需要将下边这样一些数据添加到我们的日志中,以便我们通过这些数据能识别出是谁在调用谁的接口:

  • 消息类型(例如请求、响应、广播、事件等)
  • 消息的发送者
  • 消息的接收者

3.3 额外的元数据

根据我们的架构和技术环境,用更有价值的元数据来丰富我们的日志也是很有用的,比如说:

  • 消息序列号
  • 会话 ID
  • 实例 ID
  • 进程 ID
  • 线程 ID

当这些信息都以如此一致和确定的方式提供后,可想而知,我们可以轻松地以编程的方式来处理这些数据并获得有价值的结果。

3.4 检查可用的内置元数据

我们还应该清楚,工程中的日志组件已经为我们提供了一些有用的内置元数据。例如,Android 日志组件的 API 强制我们显式指定日志级别和标签以及实际日志内容:

private static final String TAG = "MyApplication";
Log.i(TAG, "My important trace")

当在日志文件中看到相应的日志记录时,我们也会意识到,框架为我们隐式地放置了一些额外的元数据:

10-18 11:05:19.112  4612  4628 I MyApplication: My important trace
  • 时间信息(10-18 11:05:19.112)
  • 进程 ID (4612)
  • 线程 ID (4628)

其他日志框架可能会提供不同的或更多的元数据,例如行号、类名、方法名等。通常可以配置日志内容和布局。在某些情况下,还可以动态附加一些额外的上下文信息。

由于在大多数项目中,底层的日志框架是不可调整的,我们应该首先检查它为我们提供了哪些可用的内置元数据。最终,我们需要将我们收集的元数据与内置元数据对齐,以避免冗余。

4、如何一致地记录日志?

众所周知:软件接口会随着时间的推移而发展。但是,如果日志是手动实现的,并且不与更改的接口一起维护,则日志会保持不变。这是一个潜在的风险,因为日志分析可能会把我们引向错误的方向,甚至让我们得出错误的结论,仅仅是因为日志数据与接口规范不一致。

因此,只要有可能,我们就应该避免手动记录服务接口调用。

4.1 生成的日志记录优于手动记录的日志

假设我们很幸运,在我们的项目结构中,服务接口是可用的声明性模型,用接口描述语言(IDL)或任何其他机器可读的模式指定。这些模型是生成处理信息发送和接收的模板代码的输入。这也是我们钩住并生成相应的日志调用的地方。

4.2 非侵入性的日志记录

在一些技术环境中,系统甚至可能为我们提供挂钩到消息传输机制本身的设施。如果是这种情况,我们应该更偏向选择这种方式,在框架内拦截消息。然后,应用程序代码将保持不变。

4.3 面向切面的日志记录

我们也可能有机会遇到允许使用面向切面编程 (AOP) 的技术环境。一些编程语言(如 Java)具有可用的 AOP 实现。它可以将横切关注点(如日志记录)从应用程序代码中分离出来。
检查你的基础设施提供了什么,但通常有一种方法可以避免手动记录。

5、结论

我们现在有了如何为服务接口应用结构化日志的指南和方法。我们对什么、如何、在哪里以及何时以一致的方式记录有价值的数据有了一个概念。
最后,我们需要检查结构化日志方法如何在你的环境中实际应用。但这不能笼统地回答,因为这在很大程度上取决于你的要求和现有的基础技术架构。

通信和消息传输框架的作用范围是很巨大的。这同样适用于日志基础设施。它们的API和设施能力会推动结构化日志在你的项目结构中实现的方式。

最后说一句(求关注,莫错过)

如果这篇文章对您有所帮助,或者有所启发的话,帮忙扫描下发二维码关注一下,关注公众号:「架构染色」,进行交流和学习。您的支持是我坚持写作最大的动力。

原文信息

原文作者 Torsten Mosis 是 systemticks GmbH的软件架构师

原文:Structured Logging - for a better system understanding

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
相关文章
|
3月前
|
运维 安全 Linux
【揭秘】如何轻松掌控Linux系统命脉?——一场探索日志文件奥秘的旅程,带你洞悉系统背后的故事!
【8月更文挑战第21天】日志文件对Linux系统至关重要,记录着包括应用行为、组件状态和安全事件在内的系统活动,如同系统的“黑匣子”。掌握日志查看技巧是系统管理的基础技能,有助于快速诊断问题。常用命令包括`cat`、`tail`和`grep`等,可用于查看如`/var/log/messages`和`/var/log/auth.log`等系统日志文件,以及特定应用的日志。`journalctl`则用于查看systemd服务日志。此外,`logrotate`工具可管理日志文件的滚动和归档,确保系统高效运行。
46 4
|
3月前
|
存储 数据采集 数据处理
【Flume拓扑揭秘】掌握Flume的四大常用结构,构建强大的日志收集系统!
【8月更文挑战第24天】Apache Flume是一个强大的工具,专为大规模日志数据的收集、聚合及传输设计。其核心架构包括源(Source)、通道(Channel)与接收器(Sink)。Flume支持多样化的拓扑结构以适应不同需求,包括单层、扇入(Fan-in)、扇出(Fan-out)及复杂多层拓扑。单层拓扑简单直观,适用于单一数据流场景;扇入结构集中处理多源头数据;扇出结构则实现数据多目的地分发;复杂多层拓扑提供高度灵活性,适合多层次数据处理。通过灵活配置,Flume能够高效构建各种规模的数据收集系统。
66 0
|
3天前
|
存储 Linux Docker
centos系统清理docker日志文件
通过以上方法,可以有效清理和管理CentOS系统中的Docker日志文件,防止日志文件占用过多磁盘空间。选择合适的方法取决于具体的应用场景和需求,可以结合手动清理、logrotate和调整日志驱动等多种方式,确保系统的高效运行。
8 2
|
14天前
|
XML JSON 监控
告别简陋:Java日志系统的最佳实践
【10月更文挑战第19天】 在Java开发中,`System.out.println()` 是最基本的输出方法,但它在实际项目中往往被认为是不专业和不足够的。本文将探讨为什么在现代Java应用中应该避免使用 `System.out.println()`,并介绍几种更先进的日志解决方案。
39 1
|
22天前
|
监控 网络协议 安全
Linux系统日志管理
Linux系统日志管理
37 3
|
27天前
|
监控 应用服务中间件 网络安全
#637481#基于django和neo4j的日志分析系统
#637481#基于django和neo4j的日志分析系统
32 4
|
3月前
|
存储 消息中间件 人工智能
AI大模型独角兽 MiniMax 基于阿里云数据库 SelectDB 版内核 Apache Doris 升级日志系统,PB 数据秒级查询响应
早期 MiniMax 基于 Grafana Loki 构建了日志系统,在资源消耗、写入性能及系统稳定性上都面临巨大的挑战。为此 MiniMax 开始寻找全新的日志系统方案,并基于阿里云数据库 SelectDB 版内核 Apache Doris 升级了日志系统,新系统已接入 MiniMax 内部所有业务线日志数据,数据规模为 PB 级, 整体可用性达到 99.9% 以上,10 亿级日志数据的检索速度可实现秒级响应。
AI大模型独角兽 MiniMax 基于阿里云数据库 SelectDB 版内核 Apache Doris 升级日志系统,PB 数据秒级查询响应
|
1月前
|
监控 Linux 测试技术
Linux系统命令与网络,磁盘和日志监控总结
Linux系统命令与网络,磁盘和日志监控总结
52 0
|
1月前
|
监控 Linux 测试技术
Linux系统命令与网络,磁盘和日志监控三
Linux系统命令与网络,磁盘和日志监控三
36 0
|
3月前
|
缓存 NoSQL Linux
【Azure Redis 缓存】Windows和Linux系统本地安装Redis, 加载dump.rdb中数据以及通过AOF日志文件追加数据
【Azure Redis 缓存】Windows和Linux系统本地安装Redis, 加载dump.rdb中数据以及通过AOF日志文件追加数据
123 1
【Azure Redis 缓存】Windows和Linux系统本地安装Redis, 加载dump.rdb中数据以及通过AOF日志文件追加数据