記錄
Symfony 隨附兩個極簡的 PSR-3 logger:用於 HTTP 環境的 Logger 以及用於 CLI 環境的 ConsoleLogger。根據 十二要素應用程式方法,它們將從 WARNING
級別開始的訊息傳送到 stderr。
最小記錄級別可以透過設定 SHELL_VERBOSITY
環境變數來變更
SHELL_VERBOSITY 值 |
最小記錄級別 |
---|---|
-1 |
ERROR |
1 |
NOTICE |
2 |
INFO |
3 |
DEBUG |
最小記錄級別、預設輸出和記錄格式也可以透過將適當的引數傳遞至 Logger 和 ConsoleLogger 的建構子來變更。
Logger 類別可透過 logger
服務取得。若要傳遞您的組態,您可以覆寫 "logger" 服務定義。
如需 ConsoleLogger
的詳細資訊,請參閱使用 Logger。
記錄訊息
若要記錄訊息,請在您的控制器或服務中注入預設的 logger
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
use Psr\Log\LoggerInterface;
// ...
public function index(LoggerInterface $logger): Response
{
$logger->info('I just got the logger');
$logger->error('An error occurred');
// log messages can also contain placeholders, which are variable names
// wrapped in braces whose values are passed as the second argument
$logger->debug('User {userId} has logged in', [
'userId' => $this->getUserId(),
]);
$logger->critical('I left the oven on!', [
// include extra "context" info in your logs
'cause' => 'in_hurry',
]);
// ...
}
建議在記錄訊息中新增預留位置,因為
- 檢查記錄訊息更容易,因為許多記錄工具會將除了其中一些變數值之外相同的記錄訊息分組在一起;
- 翻譯這些記錄訊息容易得多;
- 這對安全性更好,因為實作可以以感知內容的方式完成跳脫。
logger
服務針對不同的記錄級別/優先順序有不同的方法。請參閱 LoggerInterface 以取得 logger 上所有方法的清單。
Monolog
Symfony 與最受歡迎的 PHP 記錄程式庫 Monolog 無縫整合,以建立和儲存各種不同位置的記錄訊息,並觸發各種動作。
例如,使用 Monolog,您可以設定 logger 以根據訊息的級別執行不同的操作 (例如,當發生錯誤時傳送電子郵件)。
在使用基於 Monolog 的 logger 之前,請執行此命令來安裝它
1
$ composer require symfony/monolog-bundle
以下各節假設已安裝 Monolog。
記錄檔儲存位置
預設情況下,當您處於 dev
環境時,記錄條目會寫入 var/log/dev.log
檔案。
在 prod
環境中,記錄會寫入 STDERR PHP stream,這在部署到沒有磁碟寫入權限的伺服器的現代容器化應用程式中最有效。
如果您偏好將生產環境記錄儲存在檔案中,請將記錄處理器的 path
設定為要使用的檔案路徑 (例如 var/log/prod.log
)。
處理器:將記錄寫入不同位置
logger 有一個處理器堆疊,每個處理器都可用於將記錄條目寫入不同的位置 (例如,檔案、資料庫、Slack 等)。
提示
您也可以設定記錄 "通道",它們就像類別。每個通道都可以有其自己的處理器,這表示您可以將不同的記錄訊息儲存在不同的位置。請參閱如何將訊息記錄到不同的檔案。
Symfony 在預設的 monolog.yaml
組態檔中預先設定了一些基本處理器。查看這些內容以取得一些真實世界的範例。
此範例使用兩個處理器:stream
(寫入檔案) 和 syslog
以使用 syslog 函數寫入記錄
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
# config/packages/prod/monolog.yaml
monolog:
handlers:
# this "file_log" key could be anything
file_log:
type: stream
# log to var/log/(environment).log
path: "%kernel.logs_dir%/%kernel.environment%.log"
# log *all* messages (debug is lowest level)
level: debug
syslog_handler:
type: syslog
# log error-level messages and higher
level: error
這定義了一個處理器的堆疊,每個處理器都按照定義的順序呼叫。
注意
如果您想要透過另一個組態檔覆寫 monolog
組態,您將需要重新定義整個 handlers
堆疊。這兩個檔案中的組態無法合併,因為順序很重要,而合併不允許您控制順序。
修改記錄條目的處理器
某些處理器不是將記錄檔寫入某處,而是用於在將記錄條目傳送到其他處理器之前對其進行篩選或修改。一個強大的內建處理器稱為 fingers_crossed
,預設在 prod
環境中使用。它在請求期間儲存所有記錄訊息,但只有當其中一則訊息達到 action_level
時,才會將它們傳遞到第二個處理器。以這個範例為例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
# config/packages/prod/monolog.yaml
monolog:
handlers:
filter_for_errors:
type: fingers_crossed
# if *one* log is error or higher, pass *all* to file_log
action_level: error
handler: file_log
# now passed *all* logs, but only if one log is error or higher
file_log:
type: stream
path: "%kernel.logs_dir%/%kernel.environment%.log"
# still passed *all* logs, and still only logs error or higher
syslog_handler:
type: syslog
level: error
現在,如果甚至有一個記錄條目的級別為 LogLevel::ERROR
或更高,則該請求的所有記錄條目都會透過 file_log
處理器儲存到檔案中。這表示您的記錄檔將包含有關問題請求的所有詳細資訊 - 使偵錯變得更加容易!
提示
名為 "file_log" 的處理器不會包含在堆疊本身中,因為它用作 fingers_crossed
處理器的巢狀處理器。
所有內建處理器
Monolog 隨附許多內建處理器,用於透過電子郵件傳送記錄、將它們傳送到 Loggly 或在 Slack 中通知您。這些都在 MonologBundle 本身中記錄。如需完整清單,請參閱 Monolog 組態。
如何輪替您的記錄檔
隨著時間的推移,記錄檔可能會變得非常龐大,無論是在開發期間還是在生產環境中。一種最佳實務解決方案是使用像 logrotate Linux 命令這樣的工具,在記錄檔變得太大之前輪替它們。
另一種選擇是讓 Monolog 為您輪替檔案,方法是使用 rotating_file
處理器。此處理器每天建立一個新的記錄檔,並且還可以自動移除舊檔案。若要使用它,請將處理器的 type
選項設定為 rotating_file
1 2 3 4 5 6 7 8 9 10
# config/packages/prod/monolog.yaml
monolog:
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
在服務內部使用 Logger
如果您的應用程式使用服務自動組態,則任何類別實作 Psr\Log\LoggerAwareInterface
的服務都會收到對其方法 setLogger()
的呼叫,其中預設的 logger 服務作為服務傳遞。
如果您想在自己的服務中使用預先設定的 logger,該 logger 使用特定的通道 (預設為 app
),您可以自動裝配 monolog 通道,或使用 monolog.logger
標籤以及 Dependency Injection 參考中說明的 channel
屬性。
在長時間執行的程序中處理記錄
在長時間執行的程序期間,記錄可能會累積到 Monolog 中,並導致一些緩衝區溢位、記憶體增加,甚至不合邏輯的記錄。可以使用 Monolog\Logger
實例上的 reset()
方法清除 Monolog 記憶體中的資料。這通常應在長時間執行的程序正在處理的每個作業或任務之間呼叫。