使用Monolog做日誌
Symfony自帶了一個外部函式庫 - 叫做 Monolog - 它允許你建立「可以存放在各種不同地方」的日誌。
記錄一則訊息 ¶
要記錄一個訊息,從控制器中的容器取出logger
服務:
public function indexAction(){ $logger = $this->get('logger'); $logger->info('I just got the logger'); $logger->error('An error occurred'); $logger->critical('I left the oven on!', array( // include extra "context" info in your logs / 在日志中附带额外的“上下文”信息 'cause' => 'in_hurry', )); // ...}
logger 服務針對不同的日誌等級/優先權擁有不同的方法。你可以基於資訊的 等級 來設定logger去做不同的事(如 有錯誤發生時發送郵件)。
參考 LoggerInterface 以了解logger的全部方法清單。
日誌被存在哪裡 ¶
對於把日誌存放在何處 的設定資訊,位於特定的environment 設定檔: config_dev.yml
和config_prod.yml
之中。
當你處於 dev
環境時,日誌檔案入口被預設寫進了 var/logs/dev.log
檔案。在prod
環境下,日誌被寫入var/logs/prod.log
,但卻僅 在請求過程中遇到錯誤或是遇到高優先權日誌時才會發生(如error()
, critical()
, alert()
或emergency()
)。
要控制存放位置,你要配置不同的 handlers(控制器)來控制日誌入口點(entries),必要時修改它們,最終儲存它們。
Handlers: 把日誌寫入不同的位置 ¶
logger自帶了一組handlers,每一種都用來把日誌入口寫入到不同的位置(如,文件,資料庫,Slack等)。
你 還 能配置日誌的 "channels"(頻道),這就像分類。每個頻道可以有其 自己的 handlers,這意味著你可以把不同的資訊記錄到不同的地方。參考 如何把日誌資訊寫入不同的檔案#。
Symfony在 config_dev.yml
和 config_prod.yml
檔案中預設了一些handlers。要了解真實用例不妨查看它們。
下例使用了兩個 handlers: stream
(用於寫入檔案) 和syslog
,後者使用syslog
函數來完成日誌:
YAML:# app/config/config.ymlmonolog: handlers: # this "file_log" key could be anything # 这个 "file_log" 键可以是任何(合法)字符 file_log: type: stream # log to var/logs/(environment).log # 写入到 var/logs/(environment).log path: "%kernel.logs_dir%/%kernel.environment%.log" # log *all* messages (debug is lowest level) # 把 *全部* 信息写入(debug是最低级别) level: debug syslog_handler: type: syslog # log error-level messages and higher # 记录 error-level(ERROR级别)或更高级别(的信息) level: error
XML:<!-- app/config/config.xml --><?xml version="1.0" encoding="UTF-8" ?><container xmlns="http://symfony.com/schema/dic/services" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:monolog="http://symfony.com/schema/dic/monolog" xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/monolog http://symfony.com/schema/dic/monolog/monolog-1.0.xsd"> <monolog:config> <monolog:handler name="file_log" type="stream" path="%kernel.logs_dir%/%kernel.environment%.log" level="debug" /> <monolog:handler name="syslog_handler" type="syslog" level="error" /> </monolog:config></container>
PHP:// app/config/config.php$container->loadFromExtension('monolog', array( 'handlers' => array( 'file_log' => array( 'type' => 'stream', 'path' => '%kernel.logs_dir%/%kernel.environment%.log', 'level' => 'debug', ), 'syslog_handler' => array( 'type' => 'syslog', 'level' => 'error', ), ),));
本例定義了一群組 handler,它們會依照各自被定義的順序被呼叫。
可修改日誌入口的handlers ¶
#並非將日誌寫入某處的文件, 一些 handlers可用於「在將日誌傳送到其他 handlers之前」過濾和修改它們。一個內建的名為 fingers_crossed
的強大handleris預設用於 prod
環境下。它在請求過程中儲存 全部 日誌訊息,卻 只是 將它們傳入第二個handler,如果某條訊息達到 action_level
等級的話。看以下例程:
YAML:# app/config/config.ymlmonolog: handlers: filter_for_errors: type: fingers_crossed # if *one* log is error or higher, pass *all* to file_log # 如果 *一条* 日志是error或更高(的级别),把它们 *全部* 传入file_log action_level: error handler: file_log # now passed *all* logs, but only if one log is error or higher # 现在传入了 *全部* 日志,但只是那些error或更高级别的 file_log: type: stream path: "%kernel.logs_dir%/%kernel.environment%.log" # still passed *all* logs, and still only logs error or higher # 仍然传入了 *全部* 日志,并且仍然都是error或更高级别的 syslog_handler: type: syslog level: error
XML:<!-- app/config/config.xml --><?xml version="1.0" encoding="UTF-8" ?><container xmlns="http://symfony.com/schema/dic/services" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:monolog="http://symfony.com/schema/dic/monolog" xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/monolog http://symfony.com/schema/dic/monolog/monolog-1.0.xsd"> <monolog:config> <monolog:handler name="filter_for_errors" type="fingers_crossed" action-level="error" handler="file_log" /> <monolog:handler name="file_log" type="stream" path="%kernel.logs_dir%/%kernel.environment%.log" level="debug" /> <monolog:handler name="syslog_handler" type="syslog" level="error" /> </monolog:config></container>
PHP:// app/config/config.php$container->loadFromExtension('monolog', array( 'handlers' => array( 'filter_for_errors' => array( 'type' => 'fingers_crossed', 'action_level' => 'error', 'handler' => 'file_log', ), 'file_log' => array( 'type' => 'stream', 'path' => '%kernel.logs_dir%/%kernel.environment%.log', 'level' => 'debug', ), 'syslog_handler' => array( 'type' => 'syslog', 'level' => 'error', ), ),));
現在,如果某一日誌入口(log entry,譯註:即「位於某處的日誌檔案」)遇到了error
或更高等級的(資訊),則該請求的所有 日誌入口將透過file_log
handler被存成一個檔案。這意味著你的日誌檔案將包含問題請求的 全部 相關細節 - 這讓調試變得更容易!
名為"file_log" 的handler將不包括在控制器堆疊中,因為它是作為fingers_crossed
handler的巢狀控制器來使用。
如果你希望透過另一個設定檔來覆寫monolog
設定訊息,你需要重新定義整個handlers
stack(控制器堆疊)。這兩個檔案中的設定資訊不能被合併,因為(handler的)順序很關鍵,一旦合併就無法控制順序。
所有的內建handler ¶
Monolog內建了許多 用於發送日誌郵件的handlers,把它們發送到Loggly,或者在Slack中通知你。這些功能在MonologBundle中都有文件。完整的清單請參考 Monolog Configuration。
如何翻轉你的日誌檔案 ¶
時間一長,不管是開發環境還是生產環境,日誌檔案會變得極為巨大 。解決方案中的一個最佳實踐是使用諸如 logrotate 這種Linux command來在日誌檔案巨型化之前反轉之。
另一個選項是使用rotating_file
handler來令Monolog去反轉日誌檔。這個控制器每天會創建新的日誌文件,並自動刪除舊的。要使用它,把控制器中的 type
選項設為 rotating_file
即可:
PHP:// app/config/config_dev.php$container->loadFromExtension('monolog', array( 'handlers' => array( 'main' => array( 'type' => 'rotating_file', 'path' => "%kernel.logs_dir%/%kernel.environment%.log", 'level' => 'debug', // max number of log files to keep // defaults to zero, which means infinite files 'max_files' => 10, ), ),));
XAML:<!-- app/config/config_dev.xml --><?xml version="1.0" encoding="UTF-8" ?><container xmlns="http://symfony.com/schema/dic/services" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:monolog="http://symfony.com/schema/dic/monolog" xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/monolog http://symfony.com/schema/dic/monolog/monolog-1.0.xsd"> <monolog:config> <!-- "max_files": max number of log files to keep defaults to zero, which means infinite files --> <monolog:handler name="main" type="rotating_file" path="%kernel.logs_dir%/%kernel.environment%.log" level="debug" max_files="10" /> </monolog:config></container>
YAML:# app/config/config_dev.ymlmonolog: handlers: main: type: rotating_file path: '%kernel.logs_dir%/%kernel.environment%.log' level: debug # max number of log files to keep # defaults to zero, which means infinite files # 要保留的日志文件的最大数量,默认是零,即,无限个文件 max_files: 10