You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 21:50:13