Laravel全局生成日志ID并记录至容器的实现方案咨询
Laravel 全局为所有日志添加统一请求ID的实现方法
当然可以实现全局统一生成日志ID,无需在每次打日志时手动传入。结合你已经尝试的中间件思路,这里提供两种完善的全局实现方案,覆盖HTTP请求和命令行任务场景:
方案一:全局中间件 + 日志上下文共享(适配HTTP请求)
你之前的中间件思路是可行的,只需完善配置让日志自动携带ID:
1. 完善全局中间件
修改你的AssignRequestId中间件,确保ID存入容器和请求实例,同时共享到日志上下文:
<?php namespace App\Http\Middleware; use Closure; use Illuminate\Support\Facades\Log; use Ramsey\Uuid\Uuid; class AssignRequestId { public function handle($request, Closure $next) { $requestId = Uuid::uuid4()->toString(); // 存入请求实例,方便后续调用 $request->attributes->set('request-id', $requestId); // 绑定到容器,全局可获取 app()->instance('request-id', $requestId); // 共享到日志上下文,所有日志自动携带 Log::shareContext(['request-id' => $requestId]); return $next($request); } }
2. 注册全局中间件
在app/Http/Kernel.php的$middleware数组中注册该中间件,确保所有HTTP请求都经过:
protected $middleware = [ // ...其他默认中间件 \App\Http\Middleware\AssignRequestId::class, ];
3. 配置日志格式
修改config/logging.php,指定日志格式包含上下文信息,让request-id自动显示在日志中:
'channels' => [ 'stack' => [ 'driver' => 'stack', 'channels' => ['single'], ], 'single' => [ 'driver' => 'single', 'path' => storage_path('logs/laravel.log'), 'level' => env('LOG_LEVEL', 'debug'), 'formatter' => \Monolog\Formatter\LineFormatter::class, 'formatter_with' => [ 'format' => "[%datetime%] %level_name%: %message% | Request-ID: %context.request-id%\n", 'dateFormat' => 'Y-m-d H:i:s', ], ], ];
方案二:Monolog处理器(适配所有日志场景)
如果需要覆盖命令行任务、队列等非HTTP场景的日志,可使用Monolog自定义处理器:
1. 创建自定义日志处理器
<?php namespace App\Logging; use Monolog\Processor\ProcessorInterface; use Ramsey\Uuid\Uuid; class RequestIdProcessor implements ProcessorInterface { public function __invoke(array $record): array { // 优先使用HTTP请求中生成的ID,否则生成新UUID $requestId = app()->bound('request-id') ? app('request-id') : Uuid::uuid4()->toString(); // 将ID存入日志的extra字段 $record['extra']['request-id'] = $requestId; return $record; } }
2. 配置日志通道使用处理器
修改config/logging.php,为目标日志通道添加处理器:
'single' => [ 'driver' => 'single', 'path' => storage_path('logs/laravel.log'), 'level' => env('LOG_LEVEL', 'debug'), 'processors' => [ \App\Logging\RequestIdProcessor::class, ], 'formatter' => \Monolog\Formatter\LineFormatter::class, 'formatter_with' => [ 'format' => "[%datetime%] %level_name%: %message% | Request-ID: %extra.request-id%\n", 'dateFormat' => 'Y-m-d H:i:s', ], ],
全局获取Request-ID
在项目任何地方,都可以通过容器获取当前请求/任务的ID:
$requestId = app('request-id');
内容的提问来源于stack exchange,提问作者cong wang
相关产品推荐
相关产品推荐

