日志未写入 runtime/logs/ 的主因是 log 组件 targets 未配置或未生效,需在 config/web.php 中显式声明 filetarget 并确保 logfile 使用 @runtime 别名、runtime 目录权限正确;慢查询需通过 categories 和 levels 精准过滤;堆栈丢失因 yii::error 第二参数非 exception 实例;文件轮转依赖 maxfilesize(单位 kb)和磁盘写权限。

日志为什么没写进 runtime/logs/?先查 targets 是否生效
Yii 2 的 log 组件默认不写文件,只往 PHP 错误日志或浏览器控制台(ChromePhpTarget)输出。调用 Yii::error() 却找不到 app.log,大概率是 targets 根本没配,或者配了但没被加载。
必须在 config/web.php 的 components 中显式声明 'log',且 targets 数组里至少有一个是 yii\log\FileTarget:
'log' => [
'targets' => [
[
'class' => 'yii\log\FileTarget',
'levels' => ['error', 'warning', 'info'],
'logFile' => '@runtime/logs/app.log',
],
],
],
-
logFile必须用别名(如@runtime),不能写相对路径logs/app.log,否则会静默失败 -
runtime/目录需对 Web 进程用户(如www-data)有rw-权限;ls -l runtime/看是否可写 - 别在控制器或
bootstrap里动态Yii::$app->log->targets[] = ...—— 初始化后修改无效
怎么只记录数据库慢查询?用 categories + levels 精准过滤
盲目开全量日志会导致文件膨胀、关键错误被淹没。Yii 支持按 category(分类)和 levels(级别)双维度筛选,比如只想捕获数据库执行耗时过长的 error 和 warning:
[
'class' => 'yii\log\FileTarget',
'levels' => ['error', 'warning'],
'categories' => ['yii\db\Command::execute', 'yii\db\Command::query'],
'logFile' => '@runtime/logs/db-slow.log',
],
-
categories支持通配符:'yii\db.*'匹配所有数据库操作,'yii\db\Command::execute'只匹配执行语句(不含查询) - category 名称大小写敏感:
'YII\DB'不匹配'yii\db' - 想同时捕获 SQL 内容?确保
yii\db\Command的enableLogging为true(默认开启)
Yii::error('msg', $e) 没打出堆栈?第二个参数类型错了
只有传入 Exception 实例,Yii 才会自动附加完整 trace。传字符串、数组、$e->getMessage() 都只记消息本身,堆栈全丢。
正确写法:
try {
$command->execute();
} catch (\Exception $e) {
Yii::error('DB execute failed', $e); // ✅ $e 是 Exception 对象
}
- 错误写法:
Yii::error('DB failed', $e->getMessage())或Yii::error('DB failed', ['code' => $e->getCode()])—— trace 彻底丢失 - 想加额外上下文又保留 trace?用关联数组:
Yii::error('DB failed', ['exception' => $e, 'sql' => $sql]),但得确认FileTarget::$except没过滤掉exception键
日志文件越滚越大?maxFileSize 单位是 KB,不是 MB
不设轮转,app.log 会无限增长。Yii 的 FileTarget 原生支持基于大小的滚动,但参数极易填错:
[
'class' => 'yii\log\FileTarget',
'maxFileSize' => 1024, // ✅ 1MB(单位是 KB)
'maxLogFiles' => 5, // 保留最多 5 个历史文件
'logFile' => '@runtime/logs/app.log',
],
-
maxFileSize是整数,单位 KB;设成1000000(想表示 1GB)会导致整数溢出,轮转逻辑直接跳过 - 轮转后文件名固定为
app.log.2026-04-18.1,无法用正则自定义;要改命名得继承FileTarget并重写rotateFiles() - 轮转不触发?除了检查
maxFileSize类型,还要确认runtime/有写权限,且磁盘未满
最常被忽略的是:logFile 路径是否真的可写,以及 maxFileSize 单位是否误当 MB 用。这两个点卡住,其他配置再对也白搭。











