日志目标应配置在 config/log.php 中并合并入 web.php;filetarget 路径须用绝对路径、maxfilesize 单位为 kb、注意 runtime 权限;emailtarget 需关闭 yii_debug 才发信;databasetarget 需扩字段长度、加索引、慎作主通道。

日志目标配置写在哪?不是在 config/web.php 里硬编码
Yii 的日志目标必须注册到 log 组件的 targets 数组中,但直接在主配置文件里堆配置容易混乱、难复用、无法按环境切换。正确做法是把目标定义拆到独立文件,再通过 require 或配置合并引入。
- 推荐路径:
config/log.php单独存放所有目标定义,返回一个数组,在config/web.php中用ArrayHelper::merge()合并 - 开发环境可启用
FileTarget+ChromePhpTarget;生产环境禁用后者,增加EmailTarget并设levels为'error' - 别在
bootstrap或控制器里动态添加 target —— 它只在应用初始化时读取一次,运行时修改无效
FileTarget 路径权限和轮转失效的常见原因
FileTarget 看似简单,但日志写不进 runtime/logs/ 或轮转不触发,90% 是权限或配置值类型不对导致的。
-
logFile必须是绝对路径,用Yii::getAlias('@runtime')拼接,别写相对路径如'logs/app.log' -
maxFileSize单位是 KB,不是 MB;设成1024表示 1MB,设1000000就会因整数溢出导致轮转逻辑跳过 - 确保
runtime/目录对 Web 进程用户(如 www-data)有写+执行权限,chown -R www-data:www-data runtime比chmod 777安全得多 - 轮转文件名格式固定为
app.log.2024-05-20.1,不能靠正则自定义;想改命名得继承FileTarget重写rotateFiles()
EmailTarget 发不出邮件?先关掉 debug 模式看真实错误
EmailTarget 在 YII_DEBUG = true 下默认静默丢弃邮件,这是 Yii 的安全设计,不是 bug。不关 debug 就永远收不到报警邮件。
- 发信失败时,错误被吞在
send()内部,不会抛异常;开启'dump' => true可把原始邮件内容打到console日志里排查结构问题 -
messageConfig中的from必须是数组格式:['no-reply@example.com' => 'My App'],字符串会报Invalid Parameter – yii\base\InvalidParamException - SMTP 配置不在
EmailTarget里,而在mail组件(yii\swiftmailer\Mailer),两个组件要配对;单独配EmailTarget的transport字段无效 - 高频报错时加
'except' => ['yii\web\HttpException:404'],避免 404 刷爆邮箱
DatabaseTarget 写不进表?字段长度和索引得手动补
DatabaseTarget 默认建表语句只生成基础字段,但实际写入时经常因 level 超长、category 截断或缺失索引导致慢查询甚至失败。
- 默认
level字段是VARCHAR(12),但自定义级别如'critical'长度为 9,'emergency'是 10 —— 建议直接扩到VARCHAR(16) -
message字段默认TEXT没问题,但trace和context如果存完整堆栈,需确认 MySQL 的max_allowed_packet是否够大(至少 8M) - 查日志时最常按
level和log_time过滤,务必手动加联合索引:ALTER TABLE log ADD INDEX idx_level_time (level, log_time); - 别把
DatabaseTarget当主日志通道 —— 写库比写文件慢一个数量级,建议只存error及以上,且开启'exportInterval' => 10批量写入
多目标共存时,levels 和 categories 的交集逻辑最容易漏:一个日志消息只有同时满足所有启用 target 的过滤条件,才会被写入那个 target。调不通时,先用 FileTarget 把原始日志捞出来,比对着干猜快得多。











