Laravel扩展Log::info遇重复日志问题求助
解决Laravel Log::listen重复记录日志的问题
这个重复记录10次的问题,核心原因是你的Log::listen回调被重复注册了。下面我来拆解原因并给出具体的修复方案:
为什么会重复?
你把监听代码放在了global.php里,这个文件在Laravel的请求生命周期中可能被多次加载(比如CLI命令、HTTP请求,或者框架某些场景下的重复初始化)。每加载一次,就会注册一个新的监听回调——当你调用Log::info时,所有已注册的回调都会执行,自然就生成了多条重复日志。
另外,你每次在回调里都创建新的Monolog实例并添加StreamHandler,不仅会加重资源消耗,也可能间接导致日志写入的重复问题。
修复方案:改用ServiceProvider注册监听
Laravel推荐用服务提供者(ServiceProvider)来处理这类启动时的逻辑,它能确保代码只执行一次。具体步骤如下:
1. 移除global.php中的监听代码
先把你放在global.php里的那段日志监听代码删掉,避免重复注册。
2. 在AppServiceProvider中注册监听
打开app/Providers/AppServiceProvider.php,在boot方法中添加以下代码:
use Illuminate\Support\Facades\Log; use Monolog\Logger; use Monolog\Handler\StreamHandler; use Illuminate\Support\Facades\Config; public function boot() { // 用静态变量标记是否已注册,确保只执行一次 static $isRegistered = false; if (!$isRegistered) { // 提前初始化Monolog实例和Handler,避免每次回调都重复创建 $logFile = storage_path('logs/laravel.enriched.log'); $enrichedLogger = new Logger('enriched_log'); $enrichedLogger->pushHandler(new StreamHandler($logFile, Logger::INFO)); Log::listen(function ($level, $message, $context) use ($enrichedLogger) { // 可选:只处理INFO级别的日志,过滤其他级别 if ($level !== 'info') { return; } // 合并原日志的context和你的额外数据 $fullContext = array_merge($context, Config::get('debug.extra_data', [])); $enrichedLogger->info($message, $fullContext); }); $isRegistered = true; } }
3. 测试验证
现在调用Log::info('example'),去storage/logs/laravel.enriched.log里查看,应该只会出现一条日志了。
额外优化建议
- 如果你的额外数据不需要每次都从配置文件读取,可以提前把它赋值给变量,提升性能。
- 如果你需要处理多个日志级别,可以调整
$level的判断逻辑,或者直接移除判断,处理所有级别的日志。
内容的提问来源于stack exchange,提问作者kwaw
相关产品推荐
相关产品推荐

