• 矛盾的开始 • 日志级别 ◦ 场景一 ◦ 场景二 ◦ 场景三 ◦ 日志级别规范与动态调整 • 记录日志 ◦ 什么时候记录日志 ◦ 日志属性 ◦ 日志安全 ◦ 日志的坏味道 • 日志的可观测性 ◦ 日志的收集 ◦ 结构化日志 ◦ 日志的存储与查询 • 总结 • Reference
理解日志并不是一件容易的事,开发人员在编写代码之时往往会纠结在某处打印的日志是不是有意义的,而 SRE 在面对缺少日志的生产问题时往往一筹莫展,Ops 在对面海量日志时往往需要花费更多的精力来维护,而项目的实际管理者在面对毫无实际业务价值的日志时,往往不想花费太多的人力和财力去管理它。
因此,在开发应用程序时遵循良好的实践,在收集管理日志时选用成熟的方案,往往能让这些矛盾得以缓解,这也就有了这一篇的分享。
首先介绍的是为什么需要记录日志,日志的作用。其实关于日志的作用无需介绍太多,因为大多数的开发人员在调试代码问题时,解决不同环境的 Bug 时都有很明确的感受以及强烈的需求。日志作为调试的助手,生产环境的救星。笔者只见过嫌弃日志打的太少的,几乎没有见过嫌弃日志打的太多的开发和运维人员。通过查询日志的方式来确定代码的分支走向,API是否请求正确,核心业务的数据是否正确,是否有错误的堆栈信息,这些都构成开发和运维人员判断代码和生产问题的第一手段。笔者难以想象如果一个复杂庞大的系统没有记录任何日志,该如何排查生产环境的 Bug。
如果有如此强烈的需求,那每一行代码都打日志来记录上下文不就行了吗?这样无论什么环境有什么代码有问题,通过搜索日志都可以排查出来。理论上这样确实可行,但是有一些问题目前无法解决,一是日志存储量的问题,常见的中大型系统日志大概在 TB 级,超大型系统的日志大概在 PB 级,根据 Cloudflare提供的数据,它每秒大概处理 4 千万的请求,这对于存储的费用来讲是一个巨大的挑战。二是搜索的性能下降,像 Elasticsearch 数据库这类常见的日志存储方案,海量的日志会导致其所维护的映射关系爆炸式增长,即使划分不同的 Index,分布式管理不同的 ElasticSearch 集群,也很难做到搜索性能不随数据量的增加而下降。三是海量日志的生成会在峰期时拖慢系统性能,增大出故障的风险。
所以综上可以得出最简单的结论,即日志既不能打印太多导致存储和管理日志太难,也不应该因为打印太少导致运维人员无法排查问题,这听起来自相矛盾,但这就是关于日志的艺术!
通常在我们打算记录日志前,我们需要判断打印日志的级别,在介绍如何确定日志级别前,我们先聊一聊日志级别的作用。首先第一点是大家所熟知的,日志级别可以帮助确定日志信息的优先级,可以有效的减少信息噪音和警报疲劳。二是在查询日志时,加到日志级别的过滤,能有效的查询到所需的日志。
常见的日志级别有以下几类,并且从低到高的顺序是:TRACE、DEBUG 、INFO、 WARN、ERROR、 FATAL。通常在本地环境,我们打印日志所配置的级别是 Trace ,即打印出所有级别的日志,但是在生产环境,会随着存储的压力,查询的性能和磁盘 IO 的影响,将日志的级别调整到 INFO 级别甚至是 ERROR 级别。这就意味着你在代码中低于该级别的日志都不会打印。
那这是不是代表我们在代码中只需要打印和生产环境匹配的日志级别呢?例如生产环境只打印 INFO 级别的日志,我们在代码中写 DEBUG 级别的日志并不会打印,也没有必要写了。有的项目管理者为了省下日志管理的费用,只在生产环境只打印 ERROR 级别的日志,那是不是 INFO 级别的日志也可以不写呢?代码中只打印和生产环境匹配的日志级别日志,这确实是笔者在大多数项目时看到的现状,但是现实情况也往往更加复杂,例如以下几个场景。
某工程师在调查生产环境中某个创建资源的 API 性能较低问题时,发现是由于该 API 在保存资源前做了写 INFO 级别的日志,将资源对象都写到日志中,由于资源的对象属性很多,所以导致在业务峰期时,代码打印出海量日志,耗尽Buffer区内存,从而拖慢主线程,造成服务性能整体下降。因此该工程师将该业务日志打印操作删除,以降低生产环境磁盘 IO 损耗,解决性能问题。
但是某天由于修改了该 API 服务调用链路上的某服务代码,导致该 API 创建出来的对象有错误,并且由于缺少了生产环境保存该资源时的日志,无法排查出是 API 的请求参数有问题,还是后续的计算逻辑有问题。这时我们只能重新修改日志级别,重新构建发布上线吗?
假设将生产环境的日志设置为 ERROR 级别。某一时刻,依赖的下游服务故障,导致请求大量超时。又由于在业务峰期 QPS 非常高的时期,短时间内集中产生大量的错误日志,导致磁盘IO急剧提高,耗费大量CPU,进而导致整个服务瘫痪。我们应该如何处理?
某工程师在排查生产问题时,发现 INFO 级别的日志还无法满足排查 Root Cause,有一个 DEBUG 日志级别的日志是他需要的,但是生产环境只有 INFO 级别,这时只能修改级别然后重新启动服务吗?