Symfony 4:Monolog默认日志器配置异常,邮件日志流向错误
我来帮你拆解这两个问题的根源,以及对应的解决办法——这些都是我在配置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的日志依赖。
解决步骤:
确认app handler的频道范围
先检查apphandler的配置,确保它只处理app频道,不要包含默认频道:app: level: info type: service id: monolog.db_handler channels: ["app"] # 这里必须只写app,不能加default强制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'检查命令的频道标签
如果你在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

