一点打log的个人经验
date
Jan 22, 2022
slug
一点打log的个人经验
status
Published
tags
Java
summary
如果log打的好,会对我们排查问题非常有帮助。如果log打的不好,一方面会增加我们排查问题时候的噪音,另一方面也会白白浪费系统资源,降低代码的可读性。
我想通过三个方面来讲,我认为什么样的log是好的,什么样的log是不好的。
type
Post
什么时候应该打log对外的接口某件事情发生之后log中应该包含哪些信息,以及如何组织这些信息描述性信息,描述发生了什么事情。能快速定位到具体case的信息,比如trackingId,key,方法参数等应该把描述性信息和case相关的信息分开log级别的选择INFO和DEBUGWARNING和ERROR
实际工作中,往往很难接触到实际的生产数据和服务运行环境。查问题的时候也往往不容易拿到问题发生时的现场。所以多数情况下,我们只能通过log来推测但是发生了什么事情,然后想办法重现。
同时,因为客观条件的限制,比如性能,容量等等,我们不能无限制的打log。所以必须搞清楚,什么地方该打log,什么时候不该打log,以及log之中应该包含什么样的信息。
如果log打的好,会对我们排查问题非常有帮助。如果log打的不好,一方面会增加我们排查问题时候的噪音,另一方面也会白白浪费系统资源,降低代码的可读性。
我想通过三个方面来讲,我认为什么样的log是好的,什么样的log是不好的。
什么时候应该打log
对外的接口
这里“对外”的定义,就是我们关心的对象跟外界交互的地方。至于粒度有多细,可以自己把握,可以是一个方法,也可以是一个服务。接口处的log可以帮助我们快速定位问题的范围。
这一点在团队大了以后尤其重要,排查跨服务的问题的时候,可以极大减少沟通成本。说的俗一点就是方便甩锅,当你没有证据的时候,想要别人相信不是你的问题,还是比较困难的。
某件事情发生之后
比如:
也就是log应该告诉我们某件事发生了,而不是将要发生
因为在事情发生之前打log,某种程度上是一种噪音,即使我们看到了这些log,给我们的信息也是非常有限的。就上面的例子来看,我们如果想知道接口调用的具体结果,还是需要去找其他的log。
相对的,在事情发生之后打log就是很必要的,我们查log时可以有很明确的判断,如果能查到log,说明事情发生了,如果没查到,说明事情没发生。
log中应该包含哪些信息,以及如何组织这些信息
描述性信息,描述发生了什么事情。
描述性的信息,应该尽量做到清晰、简洁,另外应该带有某些关键词。这样对一个对项目不太熟悉的人在查问题的时候尤其友好,可以非常容易的知道发生了什么事,并且很容易通过搜索,找到具体的代码逻辑。
能快速定位到具体case的信息,比如trackingId,key,方法参数等
这个很好理解,描述性信息是帮助我们定位代码逻辑,各种key和参数是帮助我们定位数据,还原现场。尤其是在微服务越来越流行的今天,这个信息更加重要。
应该把描述性信息和case相关的信息分开
分开有两个好处。
首先,还是对不熟悉代码的人非常友好。设想,如果描述性信息和case相关的信息通过格式化混在一起的话,通过搜索,有可能是定位不到具体代码的。
其次,如果log需要后续处理,把case相关的信息,通过特别的格式输出,对自动化处理是非常有好处的。如果混杂在一起,后续要提取关键信息会很复杂。
比如:
log级别的选择
INFO
和DEBUG
都是用来告诉我们某件事发生了,但
INFO
是用于记录业务相关的信息,而DEBUG
是用来记录代码相关的信息。WARNING
和ERROR
都是用来告诉我们,某种异常发生了。我倾向于用
WARNING
级别表示某种我们能见到的异常,而ERROR
用来表示预期之外的异常。这个区别比较微妙,实际应用中还是要尽量跟团队保持一致更加重要,因为这个级别的log经常会跟监控和报警相关了。比如:
鉴权失败,是正常业务之外的异常,但是属于我们能预期的异常。相应的,发生这种异常的时候,team可能有对应的预案。
其他异常属于我们预期之外的异常,可能我们没有对应的预案,对比
WARNING
级别,就要更严重一些,很有可能需要我们case by case的去处理。如果log打的好,会对我们排查问题非常有帮助。如果log打的不好,一方面会增加我们排查问题时候的噪音,另一方面也会白白浪费系统资源,降低代码的可读性。