這可能是php世界中最好的日志庫——monolog


由於一些歷史原因,php中並沒有內建的日志接口,故長期以來也沒一個功能完備並且應用廣泛的日志庫。在我的工作生涯中,如果系統需要記錄一些應用日志的話,基本上就是封裝一個日志類,然后把一些要記錄的字段寫入到磁盤文件。

這樣就難免要一遍一遍的造輪子,並且在沒有一個規范的情況下,記錄下來的日志也是不方便分析的。但是希望讀完本文后希望你們可以放棄自己造這種日志類的輪子了,因為幾乎你不可能造得比我們今天要介紹的主角:monolog更圓。

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中有幾個很重要的概念:

第一個:handler 日志管理器

存放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這樣易於擴展,要做到這點其實只要遵守以下幾點:

1、依賴接口而不是實現(依賴反轉、設計模式)

2、在有標准的時候遵守行業標准(psr)

在學習完了monolog的用法和設計架構之后,何不現在在mongolog之上實現一套記錄日志到關系型數據的代碼:)

更多的PHP進階學習資料盡在碼王信息,歡迎加群632109190進行討論和學習


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM