一致的、结构化的、人类可读的日志:4个有用的信息

2022-11-04  本文已影响0人  robot_test_boy

为了实现可观测性,必须从不同的数据源来收集数据,这些数据不仅来自运行中的服务,还来自基础设施。为数据定义一套通用的格式能够方便分析数据和降低使用现有工具检索这些数据所花费的代价。可以收集和使用的数据有应用日志、数据库日志、网络日志以及从底层操作系统中收集的性能数据。

日志中的有用信息

为了让日志数据实用和高效有助于了解系统的运行状况,需要确保日志中包含的某些信息能够传达出某些内容。

1.时间戳

为了能够将数据关联起来并适当排序,开发者需确保将时间戳附加到日志记录上。时间戳应该尽可能地精确和详细。每个服务都应该提供自己的时间戳,最好以毫秒为单位。时间戳还应该包含时区,建议尽可能使用GMT/UTC来收集数据。在关联来自不同时区的不同服务上的数据时可以避免出现问题。按事件发生的时间对数据进行排序会容易很多,并且在分析数据时需要的上下文信息也更少。

2.标识符

不管在什么时候,都应该在要记录的数据中尽可能多地使用唯一的标识符。当交叉引用来自多个数据源的数据时,请求ID、用户ID和其他唯一标识符是非常重要的。有了这些标识符,就能够非常高效地将不同数据源的数据分组。唯一标识符和时间戳结合起来使用是一种非常强大的手段,可以帮助了解系统中的事件流。

3.来源

确定给定日志记录的来源能够简化必要情况下的调试难度,使用的典型数据来源包括主机名、类名或模块名、函数名和文件名。在调用某个指定函数的执行时间增大时,从这个来源中收集的信息能够推断出应用出现的性能问题,因为可以推断出执行时间,即使这不是实时的。尽管它无法代替度量指标的收集,但是也能够有效地帮助发现系统瓶颈和潜在的性能问题。

4.日志等级或类别

每个日志条目都应该包含一个类别。这个类别可以是要记录的数据类型也可以是日志等级。一般来说,通常使用的日志等级有ERROR、DEBUG、INFO和WARN。可以按照这些类别对数据进行分组。有一些工具可以使用ERROR级别的消息解析日志文件检索,然后将这些消息发送给错误报告系统。这是利用日志等级或者类别信息自动实现错误报告流程而不需要显式指令的最佳示例。

结构化和可读性

想要以人类可读的格式来生成日志记录,但是这些日志同时又需要使机器易于解析。人类可读的意思是要避免出现用二进制编码的数据或者大部分人并不能理解的编码类型,比如在日志中存储图片的二进制内容。

同时还应该避免多行日志(一条日志记录占用多行),因为这会导致日志聚合工具在解析日志时将日志拆分成多个片段。这种日志很容易丢失某些与特定日志记录相关的信息,比如ID、时间戳或者来源。

建议采用JSON格式来编码日志记录,就可以使用现有的一个提供日志格式化功能的Python库logstash-formatter。Logstash库有多种语言实现,可以认为这已经是一种广泛使用的格式,不管开发者使用哪种语言来编写服务代码,该格式都是易于使用的。

Logstash是一个负责收集、处理和转发来自不同来源的事件和日志消息的工具。它提供了很多插件以配置所要收集的数据。

观察一下使用Logstash的Python库所收集的一条日志记录。这条消息使用的是Logstash的V1版本格式,应用在启动时自动生成了这条消息,并不需要其他专门代码来进行记录。

{

    "source_host" : "e7003378928a", ---  来源信息:运行应用的主机

    "pathname" : "usrlocallibpython3.6site-packagesnamekorunners.py",

  "relativeCreated" : 386.46125793457031,

    "levelno" : 20,

    "msecs" : 118.99447441101074, ---  处理该操作所花费的时间

    "process" : 1,

    "args" : [ "orders_service" ], ---  文件名、函数名、模块名以及发送日志的代码行号

    "name" : "nameko.runners",

    "filename" : "runners.py",

    "funcName" : "start",

    "module" : "runners",

    "lineno" : 64,

    "@timestamp" : "2018-02-02T18:42:09.119Z", ---  时间戳,Z表示UTC时区

    "@version" : 1, ---  日志格式化所采用的版本(logstash-formatter v1)

    "message" : "starting services: orders_service", ---  表示服务正在启动的消息

    "levelname" : "INFO", ---  日志等级或者类别

    "stack_info" : null,

    "thread" : 140612517945416,

    "processName" : "MainProcess",

    "threadName" : "MainThread",

    "msg" : "starting services: %s",

    "created" : 1520275329.1189945

}

具体怎么工作的,还是去实践一下,体会后才有更深刻的理解。

摘取自 摩根·布鲁斯和保罗·A.佩雷拉的《微服务实战》

上一篇下一篇

猜你喜欢

热点阅读