Yii日志需严格匹配配置规则:YII_DEBUG与traceLevel控制trace/debug;info/warning/error需目标显式启用levels;profile需手动加入levels;文件路径须用别名且有写权限;日志在请求结束时批量刷新,开发宜设flushInterval=1。

Yii 日志系统非常细,分级清晰、存储灵活,但“细”也意味着配置稍有偏差就可能日志不写、写错位置或漏级别——不是它不工作,而是你没对上它的规则。
日志级别怎么分?不是“越全越好”
trace、info、warning、error、profile 这五类是核心,但它们的触发和可见性高度依赖两个前提:YII_DEBUG 状态 + traceLevel 配置。
-
trace和debug(后者是trace的别名)只在YII_DEBUG = true且traceLevel > 0时才真正记录;否则调用Yii::trace()是静默丢弃的 -
info、warning、error不受YII_DEBUG影响,但必须被目标(Target)显式列入levels数组才会落盘 -
profile用于性能分析,需配合Yii::beginProfile()/Yii::endProfile(),且目标要支持(如FileTarget默认不导出 profile,得手动加'levels' => ['error', 'profile'])
文件存储路径和轮转怎么配才不踩坑?
默认日志路径是 @runtime/logs/app.log,但很多人改了 logFile 却发现日志没生成——常见原因是路径权限不足或别名未解析成功。
- 务必用 Yii 别名(如
@runtime),不要硬写绝对路径;@runtime/logs/目录必须存在且 Web 进程有写权限 - 按天分文件?别手写
date("Y-m-d")在配置里——PHP 配置是单次加载,日期不会动态更新。正确做法是用FileTarget自带的maxFiles+maxFileSize+rotateByCopy(默认开启)自动轮转 - 想按模块隔离日志?靠
categories+ 多个FileTarget:比如用户操作走user_action分类,写进@runtime/logs/user.log;支付模块走payment.*,单独存payment.log
为什么写了 Yii::error() 却看不到日志?
这不是代码问题,是日志消息压根没“发出去”——Logger 把日志暂存在内存队列,等请求结束才批量刷新到目标。如果请求中途崩溃(如 fatal error)、或没走完 Yii 生命周期(如 console 命令里忘了 Yii::$app->end()),日志就丢了。
- 开发调试时加
'flushInterval' => 1(每 1 条就刷一次),避免“以为写了,其实卡在内存里” - 确认
'bootstrap' => ['log']已配置——漏掉这句,log组件根本不会提前加载,所有Yii::xxx()调用都无效 - 检查目标是否启用:
'enabled' => YII_ENV_DEV这类条件写法很常见,但若环境变量没正确定义(比如用php -S启动却没设YII_ENV_DEV=1),目标直接被跳过
多个存储目标怎么共存又不打架?
一个 log 组件下可配多个 targets,它们是并行处理的,不是互斥的。比如你可以同时让 error 级别既写文件、又发邮件、还推到数据库,只要每个目标的 levels 和 categories 规则匹配上即可。
- 注意
except和except的优先级:它是在目标内过滤,不是全局开关。例如'except' => ['yii\web\HttpException:404']只影响当前这个FileTarget,不影响其他目标 - 敏感信息别乱记:
logVars默认记录$_GET、$_POST等,生产环境务必清空或严格限定,否则账号密码可能明文进日志 - 异步写入?
FileTarget是同步阻塞的;高并发下大量info日志会拖慢响应。真要异步,得换SyslogTarget或自定义目标+消息队列,别硬扛
categories 写错一个字符、levels 拼错大小写('Error' ≠ 'error')、@runtime 目录不可写——这些细节一出错,日志就静默失效,连报错都不会有。








