Laravel如何将SQL查询日志与请求URL、Request ID关联记录
解决方案
1. 基于请求上下文整合日志数据
我们需要在单个请求周期内暂存request_id、request_url以及该请求触发的所有SQL查询,最后统一写入单条日志。
修改请求日志中间件
更新你的中间件代码,在请求初始化时绑定标识信息,请求结束后整合所有数据写入日志:
public function handle($request, Closure $next) { // 生成request_id并绑定到当前请求实例 $requestId = md5(uniqid() . time()); $request->attributes->set('request_id', $requestId); // 初始化数组,用于存储当前请求的所有SQL查询 $request->attributes->set('sql_queries', []); $response = $next($request); // 仅当开启SQL日志配置时执行记录 if (config('app.log_sql') === true) { $sqlQueries = $request->attributes->get('sql_queries', []); if (!empty($sqlQueries)) { Log::info('Request with SQL queries', [ 'request_url' => $request->url(), 'request_id' => $requestId, 'sql_queries' => $sqlQueries, // 可选:添加响应状态码等额外信息 'response_status' => $response->getStatusCode() ]); } } return $response; }
修改AppServiceProvider的SQL监听逻辑
将原本直接写入日志的SQL,改为存入当前请求的暂存数组中:
public function boot() { if (config('app.log_sql') == true) { DB::listen(function($query) { $request = request(); // 保留你原有的SQL格式化逻辑 $formattedSql = str_replace('?', '"%s"', $query->sql); $formattedSql = vsprintf($formattedSql, $query->bindings); $formattedSql = str_replace('\\', '', $formattedSql); // 可选:添加SQL执行时间信息 $sqlData = [ 'sql' => $formattedSql, 'execution_time_ms' => $query->time ]; // 将格式化后的SQL追加到请求的暂存数组 $sqlQueries = $request->attributes->get('sql_queries', []); $sqlQueries[] = $sqlData; $request->attributes->set('sql_queries', $sqlQueries); }); } }
2. 配置开关控制
在config/app.php中添加SQL日志开关配置:
// config/app.php return [ // ...其他原有配置 'log_sql' => env('APP_LOG_SQL', false), ];
可通过.env文件快速开启/关闭:
APP_LOG_SQL=true
3. 最终日志效果
日志会以结构化形式输出,单条日志包含请求标识、地址及所有关联SQL:
[2024-05-20 14:30:00] local.INFO: Request with SQL queries {"request_url":"http://your-app.test/api/users","request_id":"a1b2c3d4e5f6","sql_queries":[{"sql":"select * from `users` where `id` = \"2\"","execution_time_ms":3},{"sql":"select * from `user_profiles` where `user_id` = \"2\"","execution_time_ms":1}],"response_status":200}
注意事项
- 该方案仅对HTTP/Web请求生效,Artisan命令等CLI任务需单独处理(可通过
$request->isMethod('GET')或判断是否为HTTP请求调整逻辑)。 - 若请求包含大量SQL查询,会临时占用内存,建议仅在调试或特定环境开启。
内容的提问来源于stack exchange,提问作者cong wang
相关产品推荐
相关产品推荐

