Seldaek/monolog中NativeMailerHandler与DeduplicationHandler搭配失效问题
问题分析与解决方案
核心原因
你的问题大概率出在Monolog版本差异或批量发送机制未触发上:
- 若使用Monolog 1.x版本,
DeduplicationHandler的flush()方法仅会清除内部缓存,不会转发调用被包裹的NativeMailerHandler的flush()。而NativeMailerHandler继承自MailHandler,默认会批量缓存日志记录,只有调用flush()时才会实际发送邮件。 - 单独使用
NativeMailerHandler时,Logger的析构函数会自动触发flushHandlers()完成邮件发送;但被DeduplicationHandler包裹后,DeduplicationHandler的flush()不执行转发,导致邮件始终停留在缓存中无法发出。
解决方案
方案1:升级到Monolog 2.x+版本
Monolog 2.x及后续版本修复了这个问题,DeduplicationHandler的flush()方法会主动调用被包裹handler的flush(),自动触发邮件发送,无需修改现有代码。
方案2:修改NativeMailerHandler的批量发送配置
将NativeMailerHandler的batchSize设为1,让每条符合级别的日志立即发送,无需等待flush():
$mailHandler = new NativeMailerHandler( $_ENV['ERROR_NOTIFICATION_EMAIL'], 'Error from My Site', 'no-reply@mydomain', Level::Error ); $mailHandler->setBatchSize(1); // 新增该行,强制单条记录立即发送
方案3:手动触发日志刷新
在脚本执行结束或合适的时机,手动调用Logger的flushHandlers(),确保所有handler完成处理:
// 在脚本逻辑末尾添加 $logger->flushHandlers();
方案4:自定义DeduplicationHandler(针对Monolog 1.x)
若无法升级版本,可创建自定义子类重写flush()方法,转发调用子handler的刷新逻辑:
class CustomDeduplicationHandler extends DeduplicationHandler { public function flush() { $this->handler->flush(); // 触发子handler的邮件发送 parent::flush(); // 执行父类的缓存清除逻辑 } } // 替换原代码中的DeduplicationHandler使用 $handlers = [ new CustomDeduplicationHandler($streamHandler), new CustomDeduplicationHandler($mailHandler) ];
内容的提问来源于stack exchange,提问作者Asis
相关产品推荐
相关产品推荐

