因为一些历史缘由,php中并无内建的日志接口,故长期以来也没一个功能完备而且应用普遍的日志库。在个人工做生涯中,若是系统须要记录一些应用日志的话,基本上就是封装一个日志类,而后把一些要记录的字段写入到磁盘文件。php
这样就不免要一遍一遍的造轮子,而且在没有一个规范的状况下,记录下来的日志也是不方便分析的。可是但愿读完本文后但愿大家能够放弃本身造这种日志类的轮子了,由于几乎你不可能造得比咱们今天要介绍的主角:monolog更圆。json
monolog是一个为5.3以上版本php开发的日志库,可是须要注意的是如今主干版本只支持php 7以上版本,若是你的服务器环境仍是php 5的话,可使用monolog的1.x版本。设计模式
值得一提的是monolog是一个符合psr-3规范的日志类库,而且符合psr-4加载规范。若是有对psr规范不太了解的同窗能够参看以下连接:http://www.php-fig.org/psr/,咱们在这里就不具体介绍这些规范了,反正知道monolog是复合当前最新行业规范的日志库就够了。服务器
若是想要在你的代码中引入monolog的话只须要执行:数据结构
composer require monolog/monolog架构
mongolog中有几个很重要的概念:app
第一个:handler 日志管理器composer
存放handler的数据结构是一个“栈”,一个日志实例能够有多个handler,经过Logger实例的pushHandler方法压入一个handler,该方法接受一个HandlerInterface类型的参数。若是你设置了多个handler,当你新增一条日志的时候,他会从栈顶开始往下传播,关心这个级别日志的handler将会处理这条日志。全部的handler都会继承AbstractProcessingHandler这个抽象类,而且只须要实现里面的抽象方法write就能够了;同时这个抽象类会继承AbstractHandler这个抽象类,这个抽象类的构造函数有两个参数:level和bubble,前者表示该handler关心的最低日志级别,是个整型,后者表示日志被当前handler处理后是否接着向下传递。参照以下代码:函数
use Monolog\Logger;学习
use Monolog\Handler\StreamHandler;
use Monolog\Handler\ErrorLogHandler;
$logger = new Logger('my_logger');
$logger->pushHandler(new StreamHandler(__DIR__.'/my_app.log', Logger::INFO));
$logger->pushHandler(new ErrorLogHandler(ErrorLogHandler::OPERATING_SYSTEM, Logger::ERROR, false));
$logger->info('码王教育——多是最具含金量的IT培训');
如上这段代码,这条日志被ErrorLogHandler处理了,而且ErrorLogHandler的bubble参数设置为false,则日志不会被写入my_app.log中了。
第二个:formatter 设置日志格式
每一个handler能够单独设置记录的日志格式,AbstractHandler抽象类中有一个setFormatter方法,该参数接受一个FormatterInterface类型的参数。能够看到monolog自带的formatter都继承自NormalizerFormatter,该类实现了format和formatBatch方法。咱们修改上面的示例代码,让两个handler记录不一样格式的日志:
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
use Monolog\Handler\ErrorLogHandler;
use Monolog\Formatter\JsonFormatter;
$logger = new Logger('my_logger');
$stream_handler = new StreamHandler(__DIR__.'/my_app.log', Logger::INFO);
$stream_handler->setFormatter(new JsonFormatter());
$logger->pushHandler($stream_handler);
$logger->pushHandler(new ErrorLogHandler(ErrorLogHandler::OPERATING_SYSTEM, Logger::INFO));
$logger->info('码王教育——多是最具含金量的IT培训');
此时能够看到my_app.log中记录的日志就变为了更方便解析的json格式了。
第三个:processor 日志处理器,用来给日志添加额外信息
存放processor的结构也是一个“栈”,意味着你也能够经过pushProcessor方法给一个Logger实例配置多个processor。咱们注意到,这里pushProcessor接受一个callable,也就是须要一个函数或者类方法,可是官方自带的这些processor都是类,随便点进去一个源码就会发现,其实这些类都用到了__invoke魔术方法,因此在被当作callable调用的时候会自动调用__invoke。咱们接着修改上面示例,给咱们的日志加上更多信息:
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
use Monolog\Handler\ErrorLogHandler;
use Monolog\Formatter\JsonFormatter;
use Monolog\Processor\UidProcessor;
use Monolog\Processor\ProcessIdProcessor;
$logger = new Logger('my_logger');
$stream_handler = new StreamHandler(__DIR__.'/my_app.log', Logger::INFO);
$stream_handler->setFormatter(new JsonFormatter());
$logger->pushHandler($stream_handler);
$logger->pushHandler(new ErrorLogHandler(ErrorLogHandler::OPERATING_SYSTEM, Logger::INFO));
$logger->pushProcessor(new UidProcessor);
$logger->pushProcessor(new ProcessIdProcessor);
$logger->info('码王教育——多是最具含金量的IT培训');
再次执行这段代码就能看到,咱们在日的后面加上了uid和process_id。
经过以上的介绍相信你对monolog的使用和库的总体架构都有一个比较系统的认识了,这个时候你应该能发现,本身开发一个handler、formatter、processor是如此简单,只用实现两个接口,再写一个匿名函数,就能彻底控制本身的日志处理方式和日志格式了。
程序开发中很重要的一点就是像monolog这样易于扩展,要作到这点其实只要遵照如下几点:
一、依赖接口而不是实现(依赖反转、设计模式)
二、在有标准的时候遵照行业标准(psr)
在学习完了monolog的用法和设计架构以后,何不如今在mongolog之上实现一套记录日志到关系型数据的代码:)
更多的PHP进阶学习资料尽在码王信息,欢迎加群632109190进行讨论和学习