1.日志的价值
首先,要明确为什么要保留日志,有了清晰的价值目标,就是有了统一的行动纲领。
如同记账本,记录每天开销,以备日后查阅统计。
记录系统日志,可以帮助我们记录应用每时每刻的运行情况,方便系统在产生故障时快速定位问题;
以及更进一步,把零散的日志收集起来,数据量大了,就能发现日志数据的规律和价值。
2. 日志基本要素
- 日志分级
- 日志分类
- 日志落盘
还是拿记账举例:
大额支出,如买房买车;小额支出,如买菜买彩票。支出额度不同,意义不同。日志也一样,「debug」、「warn」和「error」等不同的分级信息也具有不同的意义。
日常生活类支出,读书学习类支出,通过分门别类,可以统计钱都花在哪方面了。同理,我们也要分门别类统计应用程序的行为,记录不同模块的日志,以便从不同维度分析日志。
我们可以用纸质笔记本记录账单,也可以通过电子设备记录每一笔支出,方便统计分析。系统日志更要如此,可以直接输出到终端,可以写入到文本文件,或者持久化到数据库中。
2.1 日志分级
如下图,这是一个分级比较全面的设计,覆盖了几乎所有场景,具体到知乎业务我们可以有所舍弃或保留。
日志级别越低,输出的信息量越大;日志级别越高,输出的信息量越小。
在不同的环境使用不同等级的日志,比如在生产环境避免使用「debug」级别的日志,以防泄露敏感信息。
通常我们打印「info」级别日志,记得常规用户行为,如登录/查看更新资料/其他业务访问的 log 等。
- 「info」级别以下的使用
在开发过程中可以使用「debug」级别去打印程序内部信息,比如打印一些中间变量的值,打印中间处理状态等等。
对于「trace」级别的日志,这个比较低级别,通常用来本地跟踪代码的执行的详细信息。在服务端,服务器上运行的程序通常不会开启,因为日志量会很大。
对于「all」级别很少使用,可以根据情况自己定义,很多时候用到「trace」级别就很够信息量了。
- 对于「info」以上的高日志级别
「warn」级别:打印警告信息,就是可能是错误,或者是忽略的已知错误。
比如系统在调用一个不稳定的接口,有时候别人不稳定只能多次重试,这时候日志内容就会是类似『忽略第三方程序调用错误,准备重试』等信息。「error」级别:顾名思义就是,程序错误,这个可以用来打印错误数据,错误请求的事件信息,我们经常会在 catch 代码块中以「error」级别来记录此类异常。
「fatal」级别更多是在 NodeJS 引擎出现故障,或者JVM 这种引擎级别的故障可以用这个级别来打印。针对 web 应用,像访问底层数据库的失败的时候,也可以用这个「fatal」级别来记录。
出现这种问题一般是本应用的故障,或者因为网络,操作系统的故障导致的程序故障。
2.2 日志分类
分类比级别更为灵活,为日志了提供了第二个区分的维度。
例如,你可以为不同模块设置不同的分类,比如在 app1 中记录为「fromApp1」,这样就可以区分日志来源于哪个模块。
「日志分级」相当于在纵深层面对日志进行划分,「日志分类」相当于在横向维度对日志进行划分。
2.3 日志落盘
好了,现在日志有了级别和类别,解决了日志在入口处定级和分类问题。
下面就要考虑日志的出口问题(即日志输出到哪里)。
一图胜千言:
根据业务需要,可以考虑不同的落盘方式。常规做法一般会输出到文本文件中,或者持久化到数据库中方便分析。
在落盘的过程中,除了考虑输出到哪里的问题,还需要考虑如何输出的问题,如:
- 日志格式化功能
- 基本格式化功能
- 用户自定义格式化功能
- 日志过滤功能
- 输出哪些级别的日志
- 输出哪些类别的日志
- 日志切分功能
- 按时间切分
- 按体积切分
等等...
3. 总结
总之,一个完整的日志方案包括方方面面,以上只是参照主流日志库做出的分析概括。
从一个合乎逻辑的框架下出发,到具体实现过程中根据业务需要去量身定做,产出最佳实践。