关于日志模块
对于大多数程序,日志模块是不可或缺的,它是软件运行过程的录像,对于日后的数据统计,异常问题分析至关重要,所以我想谈谈一个日志系统应该满足的基本需求。这里只讨论单进程、非分布式条件下的程序,更复杂的情况不在本文讨论之内。
命令行窗口、文件
对于命令行程序,在命令行窗口中输出信息是自然的需求,能够在程序执行时方便观察到输出的日志信息,但是某些情况下,命令行输出是不够的,比如有可能这是个后台程序,没有标准输出所对应的窗口,或者这是一个大型服务器程序,日志量巨大,窗口处于狂刷状态,根本无法用肉眼查看输出,还有最重要的场景,日志是需要存档的,用于日后的数据分析。所以,文件输出也是必要的需求。
多线程
对日志系统的第一个需求就是必须支持多线程,如果日志接口不是线程安全的,还需要使用者自己处理多线程问题,那就太弱了。对使用者透明的多线程安全是基本需求。
日志缓存
第二个必要的需求是提供缓冲方式写日志文件,如果写文件日志全部是阻塞写文件,那是不可接受的,对于日志量大的系统,频繁阻塞式写日志文件那就弱爆了,也太业余了。
良好的格式
良好的日志文件输出格式,便于查阅和用脚本做日志分析,所以如下几点是我认为良好的日志格式
- 行模式,一条日志信息占用一行,不跨行
- 时间信息,没有时间信息如何做统计
- 线程信息,多线程问题就靠它来查了
- 日期分割(可选),多天的日志不存于一个日志文件中,便于按天统计数据
Python logging模块
在使用python中接触到了标准库中logging模块,可以说满足了我上文提到的所有要求,除此之外,还有远程写日志(可以做数据汇总或作为分布式系统的日志模块)等功能。logging模块主要有以下几个类,更多信息参考官方文档。
- Loggers expose the interface that application code directly uses.
- Handlers send the log records (created by loggers) to the appropriate destination.
- Filters provide a finer grained facility for determining which log records to output.
- Formatters specify the layout of log records in the final output.
这里要多说几句关于logging模块类抽象的理解,整个模块并不复杂,logger作为用户操作接口,驱动所绑定的handler列表完成日志实际处理操作,formatter处理所有字符串格式化的需求。Filter是一个过滤器功能的抽象。整个logging模块的模式很像是一个主板、键盘、显示器的抽象,用户调用日志接口(info() 类比键盘输入数据)主板就是Logger将输入内容输出给所有视频接口VGA、HDMI(类比所有注册的Handler),Handler自己去负责如何处理接收到的数据。主板和视频输出接口都有一个功能就是过滤低电流信号(Fliter)。