良好的日志记录

2020-07-24 15:28:41

要检查程序是否正在执行其应该执行的操作,可以检查给定输入的输出。但是随着系统的增长,您还需要日志记录来帮助您了解正在发生的事情。排除故障时,良好的日志消息至关重要。然而,许多开发人员没有在正确的位置记录足够的信息。

当我解决问题时,我会查看日志。有时会有一个bug导致错误的行为。其他时候没有问题-系统运行正常,但我们对它应该做什么有错误的预期。在这两种情况下,日志帮助我了解系统中发生的情况。在完成一项新功能之后,我在进行探索性测试时也会检查日志。当我尝试该功能时,我检查是否获得了预期的结果。但我也会查看日志,看它们是否符合我的预期。

根据经验,我喜欢记录任务开始、转换和结束的时间。如果是短的,可能只在尾部记录就足够了。我还喜欢登录所有任务可能失败的地方。以下是从日志消息中获取最大价值的进一步提示:

即使现代日志记录系统可以处理大量日志消息,限制记录的内容也是很好的。一些最糟糕的过度记录情况也没有什么价值。例如,如果跳过条件很简单,则“跳过的MARGIN_DATA_Available类型的消息”只是噪声,应该删除。此外,如果代码中的点A总是跟在点B之后,那么在点B处记录就足够了(可能包括来自点A的信息),而不是两条日志语句。

尽管日志记录过多有时是一个问题,但日志记录不足的情况要常见得多。这尤其适用于所有类型的失败(包括预期的和意想不到的)。调试问题时,通常需要了解任务失败的原因和原因。如果没有记录所有故障模式,那么您有时只能猜测。

通常,日志消息没有其应有的帮助。例如“连接到开票服务器”可以通过增加服务器的IP地址和端口来改进。另一个例子:在工作中,我们通过从文件中读取日历数据来初始化内存中的数据库。创建数据库时的日志消息包括文件名和文件包含的数据行数。在排除因数据文件被截断而导致的问题时,此日志消息是关键。通常,尝试添加尽可能多的动态信息。

即使日志消息自动包含文件名和行号,最好使日志消息中的文本唯一且易于grep。这使得在代码中查找日志语句变得简单快捷。如果日志消息是从字符串构建的,请确保它仍然易于grep。很多地方的“失败:%s%s”使得这一点很难实现。如果很难在文本中描述不同的案例,您甚至可以使用“FAILED(1):%s%s”等来区分案例。

如果日志记录是在一个从许多地方调用的函数中完成的,请考虑为该函数添加一个额外的参数,用于描述其大小写的字符串。这样,在日志消息中就可以清楚地知道它来自哪个案例。

当有关于要做什么的逻辑时,我喜欢将该逻辑放在可以自己进行单元测试的函数中。如果逻辑很复杂,我还想生成一些日志消息来解释所做的决定。有很多方法可以做到这一点,但我喜欢的一种方法是返回元组。元组的第一个元素是结果,第二个元素是要输出的日志消息列表(可能为空)。调用函数后,如果消息列表不为空,则会将条目连接起来并作为日志消息输出。

通过这种方式,很容易测试结果是否正确,以及日志消息是否符合我的预期。它是一个列表而不是字符串的原因是,通常关于如何做出决定可能有多个重要方面。例如,配置强制使用保证金类型,而协议的开始日期是将来。这两点可能都与协议本期不应开具发票的决定有关。此外,即使列表中有多个项目,它仍然只有一条日志语句,而不是几条,从而减少了日志记录。

偶尔我会在代码中看到这样的日志消息:“#无法获取ABC-DEF-CSA的协议数据”。不可避免的是,将会有类似的消息,例如,“#--”等等。最终,这一切都演变为一场关于谁的日志消息最能引起注意的尖叫的比赛。日志消息不应包含任何特殊字符以引起您的注意。让正在看日志的人决定他们要看什么。唯一可接受的区别是使用不同的日志级别,如警告和信息。

第一次尝试很难获得正确的日志消息。我常常要试几次才会对我所看到的感到满意。查看输出,并根据需要调整消息。例如,我在记录协议UUID时,它不会开票。但事实证明,记录协议名和参与方名称比记录UUID更有帮助,所以我更改了它。

此外,如果您正在对问题进行故障排除,而日志中没有您需要的所有信息,请记住添加它。

有时,日志可能看起来是多余的,但仍然是有用的。例如,在工作中,我们每分钟都有一个心跳API调用。这是有度量的,如果没有收到,就会发送警报。不过,我还在收到日志时添加了日志记录。因为它只是每分钟,所以不会产生太多的输出。它有助于理解系统中正在发生的事情。此外,一旦指标收集出现问题,能够检查日志并看到心跳仍在传入是件好事。

故障排除非常贴近我的心,我以前也写过关于它及其与日志记录的关系的文章:伟大的程序员编写可调试代码、查找Bugs:调试器与日志记录和基于会话的日志记录。

良好的日志记录在故障排除时非常有用。故障排除越多,您就越喜欢用正确的信息记录在正确的位置。开发新功能时,问问自己,如果新功能不起作用,您需要哪些信息,然后添加适当的日志消息。你的伐木经验是什么?请在评论中让我知道。