【译】Python日志最佳实践

原文链接:https://www.cnblogs.com/harrymore/p/16076569.html

如果你和我一样是一个后端开发者,那么日志就是通向你的应用的窗口了。不像前端,后端应用除了日志信息外没多少可以直接看到的东西。以下是我写日志的时候,遵循的一些个人原则。

记在后而非前

想当年,每艘船上都会有一本航海日志,它就如日记一般记录着每天发生的重要事件。就如航海日志那样,我们应该记录已经发生而不是即将要做的事情。

举个例子:

// 错误示例
log.info("Making request to REST API")
restClient.makeRequest()
 
// 正确做法
restClient.makeRequest()
log.info("Made request to REST API")

第一条日志其实没告诉我们啥东西,如果你读到这条日志,你并不知道REST调用是否成功了,因此你还要去看一下有没有发生异常。如果你读到这条日志并错过后续抛出的异常,相信我,你将懵逼一整天。

第二条日志就好多了。它很清晰的告诉我们前面的操作已经成功执行了。如果REST调用失败了,你也不会看到这条日志,取而代之是一个异常。

这条规则适用于所有INFO级别的日志,DEBUG日志除外。

参数和信息分离

一条典型的日志一般包含两种类型的数据。一种描述当前发生了什么事情。第二种就是在这个操作中涉及到的一系列技术参数。两种信息你最好要分开。

// 错误示例
restClient.makeRequest()
log.info("Made request to {} on REST API.", url)
 
// 正确做法
restClient.makeRequest()
log.info("Made request to REST API. [url={}]", url)

第一条日志信息是有问题的,它很难通过例如Grok patterns表达式去进行解析。对于日志工具来说,这种日志范式,自动提取id或者其他参数就变得更难了。而且可读性也变差了,试想一下,一个带有一堆参数在后面的超长URL,日志信息的一半就已经超过你的屏幕了。当然,这条日志也变得更难拓展了。如果你想加入其他参数,譬如用到的HTTP方法,你必须重写整个句子。

第二个版本就很好的避开了这些坑。因为参数列表有一个很清晰的格式,所以解析起来是很简单的。而且可读性也变好了,日志前面就是一个完整的句子。扩展也相应变得容易了,你直接把参数加到后面的列表中就可以了。

区分WARNING和ERROR

很明显,日志级别存在是有原因的,所以你需要因地制宜。WARNING和ERROR消息有几个关键的区别。

如果有一些操作,实际上是已经起作用的,但是存在一些小问题,那你就用WARNING。但如果你做了一些操作,跑都没跑起来,那就用ERROR。

看个例子:

try {
    restClient.makeRequest()
    log.info("Made request to REST API. [url={}]", url)
} catch(e: UnauthorizedException) {
    log.warn("Request to REST API was rejected because user is unauthorized. [url={}, result={}]", url, result)
} catch(e: Exception) {
    log.error("Request to REST API failed. [url={}, exception={}]", url, exception)
}

这个REST调用的结果可能有三种:

  • 正常运行,那么用INFO(调用后使用)。
  • 运行失败,并抛出了意料外的异常,那么就是ERROR。
  • 运行失败,抛出意料中的异常,使用WARNING。

因此,使用WARNING的情况,是你运行了一些东西,但是不是完美完成。使用ERROR的情况,是这个操作就完全没执行完成。

需要注意的是,WARNING(当然ERROR也是)是一个行动倡议(call to action比较难翻译,意思是看到的人需要对这个消息作出一定的响应)。如果没人需要对其作出响应或者做一些相应的事情,那你就不需要用WARNING了。

业务消息用INFO,技术消息用DEBUG

INFO日志应该像一本书,它告诉你发生了什么,而不是怎么发生的。这意味着相比技术相关的日志信息,INFO级别更适合偏业务性的日志信息。涉及技术相关信息最好还是用DEBUG。

INFO  | User registered for newsletter. [user="Thomas", email="thomas@tuhrig.de"]
INFO  | Newsletter send to user. [user="Thomas"]
INFO  | User unsubscribed from newsletter. [user="Thomas", email="thomas@tuhrig.de"]

这种类型的日志就像从我们的业务的视角给你讲了个故事,那技术相关的日志呢?

DEBUG | Saved user to newsletter list. [user="Thomas", email="thomas@tuhrig.de"]
DEBUG | Send welcome mail. [user="Thomas", email="thomas@tuhrig.de"]
INFO  | User registered for newsletter. [user="Thomas", email="thomas@tuhrig.de"]
DEBUG | Started cron job to send newsletter of the day. [subscribers=24332]
INFO  | Newsletter send to user. [user="Thomas"]
INFO  | User unsubscribed from newsletter. [user="Thomas", email="thomas@tuhrig.de"]

每条业务用例产生一行INFO日志。相应的,DEBUG日志给出这个过程执行中内部的更多的细节。

 

其他

当然了,对于好的日志来说还有很多需要注意的。你需要考虑像追踪,日志聚合和指标。但归结到记录日志上面,我真的推荐这些小规则。

致敬

Thomas

 

原文:https://tuhrig.de/my-logging-best-practices/

posted @ 2022-03-30 13:18  大师兄啊哈  阅读(110)  评论(0编辑  收藏  举报