也来谈谈日志
最近主力语言基本以 Python 为主,然后以比较分散的脚本形式由 Azkaban 进行任务调度定时之类,在感慨开发效率高,发布灵活之余也被这种方式带来的一些问题所折磨,倒不是说这种方式有多大问题,只是做的不够好,所以不像是一个 Project ,缺少对应的日志管理、配置管理、发布管理、单元测试、集成测试,然而这些工作却并不可少,所以很多都是以人肉的方式进行,有时候也无法回溯问题发生时的状况,根据之前的经验,总结下日志的一些东西先。
系统运行时会有各种各样的日志,应用服务器、Web 服务器、数据库、框架等等一般都有对应的日志输出,同时也有各种不同的级别,一般有:
-
FATAL - 严重的,造成服务中断的错误,需要马上介入,通常情况下,一个进程的生命周期中应该只记录一次 FATAL 级别的日志,即该进程遇到无法恢复的错误而退出时。
-
ERROR - 其他错误运行期错误,需要马上被处理,但是紧急程度要低于 FATAL 级别。当 ERROR 错误发生时,已经影响了用户的正常访问。从该意义上来说,用户自己操作不当,如请求参数错误等等,是绝对不应该记为 ERROR 日志的。
-
WARN - 警告信息,如程序调用了一个即将作废的接口,接口的不当使用,运行状态不是期望的但仍可继续处理等,此种级别的日志也不应太多。
-
INFO - 有意义的事件信息,如程序启动,关闭事件,收到请求事件等,INFO 日志不宜过多,通常情况下,INFO 级别的日志应该不大于 TRACE 日志的 10%。
-
DEBUG - 调试信息,可记录详细的业务处理到哪一步了,以及当前的变量状态。
-
TRACE - 该级别日志的主要作用是对系统每一步的运行状态进行精确的记录。通过该种日志,可以查看某一个操作每一步的执行过程,可以准确定位是何种操作,何种参数,何种顺序导致了某种错误的发生。
其中对于不同级别的定义和使用规范在不同的系统和团队中都略有区别,团队需要对日志级别的定义及记录方式根据自己场景做具体定义和规范。
1.为什么需要日志
日志的需求展开说也必定是五花八门,但概括下基本就是:
-
开发时需要调试信息等
-
上线运行时需要知道当前系统运行状态
-
出现问题时,有足够的信息能够还原现场
2.记录什么
- 时间
不解释,没时间还叫个什么日志
- 对应的文件、方法、模块
一方面能够快速定位,另一方面可能多个文件或方法会记录相同类似的日志,需要有所区分
-日志级别
进行分类,快速区分问题、查找
- 线程 ID、会话 ID
多线程下定位问题,多系统调用也可以根据会话 ID 进行问题追踪
- 日志信息
真正要记录的日志内容,具体记录什么根据需求或者团队规范来约定,一般要清晰明了,同时能够有足够的信息来发现追踪问题
- 其他信息
版本号、机器信息、agent 信息等等
3.最佳实践
不存在银弹,所谓最佳实践,作为总结,看看就好。
-
使用半结构化的日志消息。半结构化的格式使得可以通过工具提取日志记录中的相关信息进行分析,便于查找问题,同时利于后期管理提取。
-
使用合适的日志记录器名称。以 Java 为例,一般日志框架默认使用类的全名来作为记录器名称,大部分情况下是适用的,同时也可以方便的按照包来进行日志分级,但是对于横切类型的日志,就不是很合适,例如性能的统计,MBean 的日志,安全记录等,对于这类进行统一的命名更适用,同时也能够方便的进行日志的启用停用等。
-
日志中包含充分的信息。不解释,不包含充分的信息,还记日志干什么。
-
生产环境和测试环境适用不同的日志级别。测试环境或开发环境通常有个多的测试和问题,更加详细的日志有利于进行联调问题的快速定位,同时也有利于及早的发现潜在的问题。
-
如果可能,将性能日志作为标准化输出。
-
团队风格统一规范。一方面日志是面向读者的,另一方面风格不统一没有规范也谈不上是日志,只是 debug 信息而已。