monolog源码解读
1.monolog模块分布结构:
- Formmater:内置的日志显示格式
- Handler:各种日志处理类, 如写文件/发邮件/写队列
- Processor:内置的处理日志类
- Logger.php:log处理的接口
2.Logger.php的分析:
Logger类的部分成员变量:
- const DEBUG = 100 等:常量,代表日志级别
- handlers:存储日志处理类以栈的形式
- processers:
- name: 通道的名字
补充:
- handlers中以栈(后进先出)的形式存储着不同的handler。当一条record需要被记录日志时,它从栈顶开始向下遍历整个栈直到找到被完全处理的handler。
- processers中存储的是向record中添加额外信息的方法。
logger类的部分成员函数:
- pushHandler(HandlerInterface):向栈顶(数组头)压入Handler。参数类型是接口的形式,体现面向接口编程的特点,实现该接口的类都实现了接口规定的方法。
- popHandler():从栈顶(数组首)删除Handler。
- pushProcessor(callback):压入Processor
- popProcessor():删除Processor
- addDebug/addInfo等:调用addRecord 以不同的日志等级写入日志。
- addRecord: 先判断是否有Handler,没有的话加入最基础的Handler。遍历Handler栈找到能够处理该等级的Handler,遍历Processors,向record中添加额外的信息。调用Handler对record进行处理。
总结:logger类并不自己处理record,而是调用自己栈中的Handler来处理记录。它从栈顶到栈底遍历,直到找到能够处理该record的日志的等级的Handler。(相似于命令模式?存有command接口,调用命令时找到相应的命令实现进行执行。)
3.Handler的分析:
3.1Handler接口:
- isHandling():判断传入的record日志等级自己是否能够处理
- handle():处理record数组,率过那些无法处理,返回的bool值决定logger是否继续向下遍历
- handleBanch():立即处理record数组
- setFomatter():设置格式
3.2实现Handler接口的抽象类,AbstractHandler:
- 增加了成员变量:存储日志等级,格式,processor,是否冒泡
- 实现了部分接口 isHandling(), handleBanch(),setFomatter()
- 增加了对成员变量的操作:get,set
- 增加了close(),在对象销毁时自动调用的函数
3.3继承自AbstractHandler的抽象类,AbstractProcessingHandler:
- 实现了接口的 handle():调用write()
- 增加processRecord():为record增加额外信息。
- 增加write抽象方法:写日志
3.4 最终的实现:StreamHandler:
StreamHandler根据传入的路径writer将日志信息写入文件。
还有FirePHPHandler:实现的writer是发送HTTP头。
还有其他的Handler类,实现不同的功能 (多态?)
3.5bufferHandler:设置缓冲区,到一定数目再写日志,继承自AbstractHandler,可以包含其他Handler进行功能扩展 (装饰模式?)
总结:很多handler都继承自同一抽象类却实现不同的功能,write功能被抽出实现不同的功能(策略模式?),外部调用Handler时只要调用接口。BufferHandler继承自抽象类同时可以包含其他的Handler类进行功能的扩展(实现了缓冲区),体现了(装饰模式?)
4.Fomatter接口:
Fomatter模块和Handler相似,具体实现都是继承自接口,同时有不同的实现(策略模式)