You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Symfony 4:Monolog默认日志器配置异常,邮件日志流向错误

解决Symfony 4多日志器配置的两个核心问题

我来帮你拆解这两个问题的根源,以及对应的解决办法——这些都是我在配置Symfony日志时踩过的坑,应该能帮你快速搞定。

一、为什么main日志器会记录debug级日志?

你看到的debug日志其实是fingers_crossed handler的特性导致的:它会缓存所有级别的日志,直到触发action_level(这里是error)时,才会把缓存里的所有日志(包括之前的debug、info)一次性转发给下游的grouped handler。所以只有当系统出现error时,你才会在prod.log里看到debug日志,平时是不会有的。

解决办法:限制main日志器的处理范围

给main handler添加channels配置,排除console、app、api这些不需要它处理的频道,这样它只会处理默认频道的日志,console的命令日志就不会进入缓存了:

monolog:
 handlers:
  main:
   type: fingers_crossed
   action_level: error
   handler: grouped
   excluded_http_codes: [404, 405, 503]
   channels: ["!console", "!app", "!api"] # 排除无关频道
  # 其他handler保持不变

如果你连error触发时的缓存debug日志都不想看到,可以再加个stop_buffering: true,这样只会发送触发error的那条日志,不会连带之前的缓存:

main:
 # ... 其他配置
 stop_buffering: true

二、为什么SmtpTransport的日志会流向app频道?

这个问题大概率是服务的日志频道配置错误导致的,和你绑定LoggerInterface到main的操作不冲突,但没覆盖到SmtpTransport的日志依赖。

解决步骤:

  1. 确认app handler的频道范围
    先检查app handler的配置,确保它只处理app频道,不要包含默认频道:

    app:
     level: info
     type: service
     id: monolog.db_handler
     channels: ["app"] # 这里必须只写app,不能加default
    
  2. 强制SmtpTransport使用main日志器
    Symfony的SwiftMailer(或Mailer组件)的SmtpTransport可能默认使用了其他日志器,你需要在services.yaml里直接给它指定main日志器:

    services:
      # 全局绑定默认日志器为main
      Psr\Log\LoggerInterface: '@monolog.logger.main'
      
      # 针对SwiftMailer的SmtpTransport(Symfony 4常用SwiftMailer)
      Swift_Transport_EsmtpTransport:
        arguments:
          $logger: '@monolog.logger.main'
      
      # 如果是Symfony Mailer组件的Transport(部分Symfony 4项目会用)
      Symfony\Component\Mailer\Transport\Smtp\SmtpTransport:
        arguments:
          $logger: '@monolog.logger.main'
    
  3. 检查命令的频道标签
    如果你在services.yaml里给SendMailsCommand加了channel: app的标签,赶紧删掉,否则命令里的所有日志都会流向app频道:

    App\Command\SendMailsCommand:
      tags:
        - { name: 'console.command' }
        # 移除任何带有channel: app的标签
    

验证方案

你可以在SendMailsCommand里临时加一行代码,确认当前日志器的频道:

public function __construct(LoggerInterface $logger)
{
    parent::__construct();
    if ($logger instanceof \Monolog\Logger) {
        dump($logger->getName()); // 正常应该输出main或default
    }
}

执行命令后,如果输出是main,说明配置生效了。

内容的提问来源于stack exchange,提问作者Select0r

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 18:52:37