本文主要是介绍用日志记录美好生活的方法以及如何将日志正确地设计到系统中!,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
作者:Stanley Nguyen
译者:Elle
原文链接
正文:
在软件项目中,日志是普遍存在的,它有很多不同的形式、要求和风格。
从小到只有一个人的创业公司大到大型企业,日志记录无处不在。即使是一个简单的算法编程问题,也会涉及到一些日志记录。
我们非常依赖于日志记录来开发、维护和保持程序的正常运行。但是,关于如何在我们的系统中设计日志记录却并没有引起太多的关注。
通常情况下,日志记录会被我们视为第二考虑因素——它只有在实现时才会被添加到源代码中,就如同有种神奇的力量来帮助减轻我们系统中的日常操作难度。
我们都是日志搬运工吗?
就像任何一段代码一样,无论怎样它最终都将成为技术债务一样——我们只能通过制定严格的规则来减缓这个过程——记录器的普及速度真的是令人诧异。经过一段时间之后,我们发现自己修复记录器引起的问题的频率比记录器提供给我们有用信息的频率更高。
那么,我们该如何处理与记录器之间的混乱局面,并将他们变成我们的盟友之一而不是让过去开发遗留下来的错误而继续困扰我们呢?
目前的发展水平
在深入研究我提出的解决方案之前,让我们根据自己的观察来定义一个具体的问题描述。
那么什么是日志记录呢?以下是我从科林·埃伯哈特的文章中找到的一个有趣且中肯的笑话:
日志记录的过程是将应用程序操作和状态记录到辅助接口的过程。
这正说明了日志是如何被编码到系统中的。我们似乎都下意识地认为记录器是不属于我们系统的任何特定层的。相反,我们认为它们是属于应用程序范围内的,并可以在不同组件之间共享。
一个关于来自StackOverflow非常认可的答案
从一个简单的图表中可以看出,日志记录已经被融入到了一个简洁的架构设计系统中,看起来像下图这样:
可以肯定地说,日志记录本身就是我们应用程序中的一个子系统。如果没有经过仔细地衡量考察,它通常就会比我们想象的更快地失控。
虽然我们将日志记录设计为应用程序中的一个子系统是没有错的,但是由于传统的日志记录概念(包含4到6个级别的info
、 warn
、 error
和 debug
等等)从而导致了让开发人员经常关注错误的方向。即让我们集中注意力于格式,而不是应该注意我们为什么要写日志的实际目的。
这就是为什么我们不考虑如何处理错误就将错误注销的原因之一。这也是为什么我们在代码的每一步中都记录日志,而极具讽刺意味的是,如果中间出现生产问题,我们就无法有效地调试。
这就是为什么我提出了一个日志记录的替代框架,以及如何将日志可靠地设计到我们的系统中。
制定日志的三个关注点
这是我认为我们应该如何制定日志策略的一个框架。对于我们的日志,它有三个(而且只有三个)类别或关注点。
记录日志的第一条规则:不要记录日志
过度记录不利于我们团队的工作效率和处理常规业务的能力。
有无数的理由可以说明为什么我们不应该“在你可以的时候记录日志”。日志记录意味着需要维护更多的代码,它会在系统性能方面产生费用,更多的日志记录则会让我们接受更多的数据隐私监管审计。
如果你需要更多的理由来避免记录,看看Nikita Sobolev的这篇文章或Jeff Atwood的这篇文章。
然而,我并不建议你完全删除日志。我认为如果正确的使用日志记录,就会极大地帮助我们保持系统可靠地运行。
我只是建议我们从不进行日志记录开始,然后逐步确定需要记录的事情,而不是“把所有东西都记录下来,因为我们可能需要看它们”。
对于添加日志记录,我的经验是“如果我们不能确定查看日志的确切原因或场景,那么就不要记录日志”。
话虽如此,但当存在绝对必要的时候,我们该如何安全地引入日志记录呢? 我们应该如何构造日志并格式化其内容? 日志中需要包含哪些信息?
一、其貌不扬的日志
这是我要描述的第一种日志,也是我最不常发现的日志。 (如果我们经常发现它们,那么在我们的系统中可能会存在更大的问题!)
“其貌不扬的”是指在重大事故或意外情况下需要立即操作的日志类型(例如需要重新启动应用程序的重大性事故错误)。我们可以认为在这种情况下,使用诸如Sentry之类的
警报工具会更有意义。
尽管如此,错误日志仍然可以为我们提供更多关于这些错误的前后文,而这些错误在堆栈跟踪中是不可用的。但它们可以帮助重现这些错误,比如用户输入之类的问题。
就像它们伴随的错误一样,这些日志应该在我们的代码中保持最少的数量,并且应该放在一个单独的位置。它们也应该被当做错误处理所需的系统行为设计或记录在规范中。此外,它们应该被编辑到出错处理发生的源代码中。
虽然“其貌不扬”日志的格式和级别在团队中是属于完全优先考虑的类别,但我建议在正常关闭和重新启动应用程序之前使用log.error
或log.fatal
。 如有必要,还应附上完整的错误堆栈跟踪和函数或请求的输入数据来进行复制。
二、不良的日志
“不良的日志”是处理预期的、处理网络问题和用户输入验证等错误的日志类型。这种类型的日志只有在出现异常时才取得开发人员的注意。
再加上一个监视设置(在出现错误时向开发人员发出警报),这些日志可以很方便地缓解潜在的严重基础结构问题或安全问题。
这种类型的日志也应该在错误处理技术要求中加以说明,,如果我们在同一代码位置处理预期的和意外的错误,则可以将其捆绑在一起。
根据他们对开发人员“可见”的性质和团队的规则, log.warn
或log.error
可用于“不良的”日志。
三、优秀的日志
最后但绝对不是最不重要的,“优秀的”日志是源代码中最常出现的日志类型——但它通常是最难正确处理的。“优秀的”类型日志是指那些与应用程序的“快乐”步骤相关联的日志,表示操作成功。
由于在系统中指示启动/成功执行操作的本质,“ 优秀的”日志经常被开发人员滥用,他们被“只需要在日志中添加一点数据,我们就可能需要它”这一口号所吸引。
而且我要再次强调一下,即回到我刚刚所提到的第一个规则:“除非绝对必须,否则不要记录”。为了防止这种过度记录的发生,我们应该将“优秀的”日志作为补充主要业务逻辑的技术需求的一部分来进行记录。
最重要的是,对于我们技术规格中的每一个“优秀”日志,他们都必须通过石芯测试:在任何情况下,我们都会查看该日志(无论是客户支持请求,还是外部审计师的询问)? 只有这样,log.info才不会变成一个可怕的遗留问题来让开发人员无法看到我们的应用程序。
其他的(你需要知道的)
到目前为止,我可以假设你已经注意到我提议的日志记录策略的总体主题围绕着日志目的的清晰而具体的记录。重要的是,我们要将日志记录作为我们需求的一部分,并且我们要明确想要在每个日志的上下文中标记哪些是关键字和哪些是想要传达的信息,以便有效地对它们进行索引。
只有这样做,我们才能知道我们生成的每一个日志,进而对我们的系统有清晰的了解。
在我们的规范中,由于日志被升级为具有具体技术要求的一等公民,其含义表示它们需要:
- 根据业务和技术需求的发展来进行维护和更新
- 覆盖单元和集成测试
听起来可能需要做很多额外工作才能使我们的日志正确无误。 但是,我认为这是日志记录应得到的关注和努力,毕竟它具有使用价值。
服务于我们的日志,我们将会得到很棒的回报!
实用的迁移指南
我个人认为如果没有办法将遗留项目从凌乱的状态转移到建议的理想状态,那么对于遗留项目来说,新的日志策略(或者任何新的策略/框架)就没有意义了。
因此,对于那些对自己的系统日志感到不满意并且愿意花时间来更有效地进行日志记录的人,我有一个三步走的总体计划。
找出常见的疑点
因为我们的想法是减少垃圾日志,所以我们的第一步是识别疑点的所在位置。通过我们现在强大的文本编辑器和IDE(或者GREP,如果您在过去通过“未来之窗”阅读这篇文章的话),可以很容易地识别日志记录的所有事件。
如果这些日志显示太多,则可能需要一个文档(如果你愿意弄的话,也可以使用电子表格)来记录所有这些日志事件。
判定无用的垃圾
在确定所有疑点之后,该是清除无用的垃圾时候了。 重复的日志或无法访问的日志都是无效的行为,我们可以立即从源代码中删除它们。
对于其余的日志记录事件,是时候让其他利益相关者——例如启动项目的“初始”工程师(如果有可能的话)、产品经理、客户支持或合规人员来回答这个问题:我们需要这些日
志吗?如果需要,它们是用来做什么的?
一线希望
既然我们已经缩小了具有绝对必要的日志列表,那么将它们转换成具有文档化目的的技术需求对于为我们的日志子系统确定一个契约(或者我们可以称之为规范)是至关重要的。当日志显示错误的时候,可以问问自己能做什么,并且我们写日志的目的是什么。
在这之后,就像我们正常编写和维护软件一样,这只是一个规则问题。让我们一起努力,让写日志变得更有意义吧!
CSDN译言堂仅用于学习、研究和交流。版权归文章作者、译者和CSDN译言堂所有。如需转载,请于转载前联系该篇的译者获取授权,并在文章开头明显位置注明本文出处、译者和CSDN译言堂的完整链接,违者必究。
这篇关于用日志记录美好生活的方法以及如何将日志正确地设计到系统中!的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!