Yii 2 內建強大的日誌組件 (yii\log\Dispatcher),支援多 Target、多級別、過濾器、格式化器。本文示範生產級配置:檔案與資料庫雙輸出、開發/生產環境差異化、關鍵效能參數、日誌輪轉、結構化 JSON 輸出對接 ELK。
return [
'bootstrap' => ['log'], // 關鍵:預載入 log 組件
'components' => [
'log' => [
'traceLevel' => YII_DEBUG ? 3 : 0, // 開發環境記錄堆疊,生產關閉
'targets' => [
// 1. 檔案目標 (開發/除錯)
[
'class' => 'yii\log\FileTarget',
'levels' => ['error', 'warning', 'info', 'trace'],
'categories' => ['application', 'db', 'api'],
'logFile' => '@runtime/logs/app.log',
'maxFileSize' => 10 * 1024 * 1024, // 10MB 輪轉
'maxLogFiles' => 20, // 保留 20 個檔案
'logVars' => ['_GET', '_POST', '_SESSION', '_COOKIE', '_SERVER'], // 記錄請求上下文
'exportInterval' => 1, // 立即寫入 (開發)
],
// 2. 資料庫目標 (生產/審計)
[
'class' => 'yii\log\DbTarget',
'levels' => ['error', 'warning'],
'categories' => ['security', 'audit', 'payment'],
'logTable' => '{{%log}}',
'prefix' => function () {
return json_encode([
'user_id' => Yii::$app->user->id ?? null,
'ip' => Yii::$app->request->userIP ?? null,
'request_id' => Yii::$app->request->headers->get('X-Request-Id') ?? null,
]);
},
],
],
],
],
];
// config/params.php
return [
'log' => [
'file' => [
'levels' => YII_DEBUG ? ['error', 'warning', 'info', 'trace'] : ['error', 'warning'],
'exportInterval' => YII_DEBUG ? 1 : 100, // 生產批次寫入
],
'db' => [
'levels' => YII_DEBUG ? ['error', 'warning', 'trace'] : ['error'],
],
],
];
// config/web.php
'targets' => [
[
'class' => 'yii\log\FileTarget',
'levels' => $params['log']['file']['levels'],
'exportInterval' => $params['log']['file']['exportInterval'],
// ...
],
[
'class' => 'yii\log\DbTarget',
'levels' => $params['log']['db']['levels'],
// ...
],
],
# 運行 Migration 建立 {{%log}} 表
./yii migrate --migrationPath=@yii/log/migrations/
# 表結構 (MySQL)
CREATE TABLE `log` (
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
`level` INT NOT NULL,
`category` VARCHAR(255) NOT NULL,
`log_time` DOUBLE NOT NULL,
`prefix` TEXT,
`message` TEXT NOT NULL,
PRIMARY KEY (`id`),
INDEX `idx_level_time` (`level`, `log_time`),
INDEX `idx_category` (`category`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
| 參數 | 開發環境 | 生產環境 | 說明 |
|---|---|---|---|
| exportInterval | 1 (立即) | 100-1000 (批次) | 累積多少條訊息才寫入,減少 IO |
| traceLevel | 3 | 0 | 堆疊深度,生產關閉避免效能損耗 |
| maxFileSize | 10MB | 100MB | 單檔大小觸發輪轉 |
| maxLogFiles | 20 | 50 | 保留檔案數 |
| logVars | ['_GET','_POST',...] | [] 或 ['_SERVER'] | 記錄超全域變數,生產避免敏感資料洩漏 |
// 自定義 JsonFileTarget
namespace app\log;
use yii\log\FileTarget;
class JsonFileTarget extends FileTarget {
public function formatMessage($message) {
[$text, $level, $category, $timestamp] = $message;
$log = [
'@timestamp' => date('c', $timestamp),
'level' => $this->getLevelName($level),
'category' => $category,
'message' => $text,
'context' => $this->getContext(),
];
return json_encode($log, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) . "\n";
}
private function getContext(): array {
return [
'request_id' => Yii::$app->request->headers->get('X-Request-Id') ?? uniqid(),
'user_id' => Yii::$app->user->id ?? null,
'ip' => Yii::$app->request->userIP ?? null,
'url' => Yii::$app->request->absoluteUrl,
'method' => Yii::$app->request->method,
'memory_mb' => round(memory_get_usage(true) / 1024 / 1024, 2),
];
}
}
// 使用
'targets' => [
[
'class' => 'app\log\JsonFileTarget',
'levels' => ['error', 'warning', 'info'],
'logFile' => '@runtime/logs/app.json.log',
'exportInterval' => 10,
],
],
maxFileSize + maxLogFiles 自動輪轉 (app.log.1, app.log.2...)。/etc/logrotate.d/yii-app 管理 /var/www/app/runtime/logs/*.log,支援壓縮、郵件通知、共享腳本重啟 PHP-FPM。stdout/stderr 輸出,由 Docker logging driver (json-file, syslog, fluentd) 處理輪轉與轉發。Yii::info('User login', 'auth.login');
Yii::warning('Login failed: wrong password', 'auth.login.failed');
Yii::error('Payment gateway timeout', 'payment.gateway');
Yii::trace('SQL: ' . $sql, 'db.query'); // 只在 traceLevel > 0 時記錄
// 控制器中快速記錄
\Yii::info('Order created', 'order.create');
\Yii::error('Exception: ' . $e->getMessage(), 'order.create');
bootstrap 必須包含 log,否則 CLI/Queue 環境日誌不生效。DbTarget 使用同一資料庫連線時,大量寫入可能阻塞業務,建議獨立讀寫分離連線或改用檔案 + Logstash 收集。traceLevel = 0,否則每次記錄都生成堆疊字串,嚴重拖慢效能。logVars 生產環境務必清空或最小化,防止記錄密碼、Token、信用卡號等敏感資訊。Yii 2 日誌系統靈活強大,關鍵在於「環境差異化配置、批次寫入優化、結構化輸出、敏感資料過濾、輪轉策略」。將日誌視為可觀測性基礎設施,統一格式、標準欄位、自動收集,才能在故障排查、安全審計、業務分析中發揮最大價值。