LaravelAPI响应时间怎么记录

wen PHP项目 5

本文目录导读:

LaravelAPI响应时间怎么记录

  1. 使用中间件(推荐)
  2. 使用事件监听器
  3. 使用 Laravel Debugbar(开发环境)
  4. 自定义日志通道
  5. 记录到数据库(分析用)
  6. 监控告警(进阶)
  7. 配合监控工具
  8. 最佳实践建议

在 Laravel 中记录 API 响应时间有多种方法,以下是几种常用且高效的方案:

使用中间件(推荐)

基础版中间件

<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Log;
use Symfony\Component\HttpFoundation\Response;
class ResponseTimeLogger
{
    public function handle($request, Closure $next)
    {
        $startTime = microtime(true);
        /** @var Response $response */
        $response = $next($request);
        $duration = (microtime(true) - $startTime) * 1000; // 转换为毫秒
        // 记录日志
        Log::channel('api_response_time')->info('API Response Time', [
            'method' => $request->method(),
            'url' => $request->fullUrl(),
            'duration_ms' => round($duration, 2),
            'status_code' => $response->getStatusCode(),
            'ip' => $request->ip(),
            'user_agent' => $request->userAgent(),
        ]);
        // 可选:在响应头中添加响应时间
        $response->headers->set('X-Response-Time', round($duration, 2) . 'ms');
        return $response;
    }
}

注册中间件

app/Http/Kernel.php 中注册:

protected $routeMiddleware = [
    // ... 其他中间件
    'response.time' => \App\Http\Middleware\ResponseTimeLogger::class,
];
// 或者全局注册
protected $middleware = [
    // ...
    \App\Http\Middleware\ResponseTimeLogger::class,
];

在路由中使用

Route::middleware('response.time')->group(function () {
    Route::get('/api/users', 'UserController@index');
    Route::post('/api/users', 'UserController@store');
});

使用事件监听器

创建监听器

<?php
namespace App\Listeners;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Symfony\Component\HttpFoundation\Response;
class LogResponseTime
{
    public function handle($event)
    {
        $startTime = defined('LARAVEL_START') ? LARAVEL_START : $_SERVER['REQUEST_TIME_FLOAT'];
        $duration = (microtime(true) - $startTime) * 1000;
        if ($duration > 1000) { // 只记录超过1秒的慢请求
            Log::warning('Slow API Response', [
                'method' => request()->method(),
                'url' => request()->fullUrl(),
                'duration_ms' => round($duration, 2),
            ]);
        }
    }
}

注册事件

app/Providers/EventServiceProvider.php 中:

protected $listen = [
    'kernel.handled' => [
        'App\Listeners\LogResponseTime',
    ],
];

使用 Laravel Debugbar(开发环境)

安装包:

composer require barryvdh/laravel-debugbar --dev

自动记录所有请求的耗时信息,包括:

  • 请求时间
  • 数据库查询时间
  • 视图渲染时间

自定义日志通道

配置日志通道

config/logging.php 中添加:

'channels' => [
    'api_response_time' => [
        'driver' => 'daily',
        'path' => storage_path('logs/api-response-time.log'),
        'level' => 'info',
        'days' => 30,
    ],
    // ... 其他通道
],

高级版中间件(支持标记慢请求)

<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Log;
class AdvancedResponseTimeLogger
{
    const SLOW_THRESHOLD_MS = 2000; // 慢请求阈值
    public function handle($request, Closure $next)
    {
        $startTime = hrtime(true);
        $response = $next($request);
        $duration = (hrtime(true) - $startTime) / 1e6; // 纳秒转毫秒
        $logLevel = $duration > self::SLOW_THRESHOLD_MS ? 'warning' : 'info';
        Log::channel('api_response_time')->$logLevel('API Response', [
            'method' => $request->method(),
            'url' => $request->fullUrl(),
            'duration_ms' => round($duration, 2),
            'status_code' => $response->getStatusCode(),
            'parameters' => $request->except(['password', 'token']),
            'memory_usage_mb' => round(memory_get_peak_usage(true) / 1048576, 2),
        ]);
        return $response;
    }
}

记录到数据库(分析用)

创建数据表

Schema::create('api_response_logs', function (Blueprint $table) {
    $table->id();
    $table->string('method', 10);
    $table->string('url', 500);
    $table->float('duration_ms');
    $table->integer('status_code');
    $table->string('ip', 45)->nullable();
    $table->float('memory_mb')->nullable();
    $table->timestamps();
    $table->index('created_at');
    $table->index('duration_ms');
});

对应的 Model

<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class ApiResponseLog extends Model
{
    protected $fillable = [
        'method', 'url', 'duration_ms', 'status_code', 'ip', 'memory_mb'
    ];
}

中间件存储到数据库

public function handle($request, Closure $next)
{
    $startTime = microtime(true);
    $response = $next($request);
    ApiResponseLog::create([
        'method' => $request->method(),
        'url' => $request->fullUrl(),
        'duration_ms' => round((microtime(true) - $startTime) * 1000, 2),
        'status_code' => $response->getStatusCode(),
        'ip' => $request->ip(),
        'memory_mb' => round(memory_get_peak_usage(true) / 1048576, 2),
    ]);
    return $response;
}

监控告警(进阶)

当响应时间超过阈值时触发告警:

public function handle($request, Closure $next)
{
    $startTime = microtime(true);
    $response = $next($request);
    $duration = (microtime(true) - $startTime) * 1000;
    if ($duration > 5000) { // 5秒以上
        // 发送告警
        $this->sendAlert($request, $duration);
        // 记录到专门的慢查询日志
        Log::critical('ABNORMAL_LATENCY', [
            'duration_ms' => $duration,
            'url' => $request->fullUrl(),
            'session_id' => session()->getId(),
        ]);
    }
    return $response;
}
private function sendAlert($request, $duration)
{
    // 发送邮件、Slack、钉钉等通知
    // 例如使用 Laravel 的通知系统
}

配合监控工具

Laravel Telescope(推荐)

composer require laravel/telescope

自动记录所有请求的详细信息。

Pulse(Laravel 11+)

php artisan install:pulse

内置响应时间监控仪表板。

最佳实践建议

  1. 按环境区分:开发环境使用 Debugbar,生产环境使用中间件
  2. 分级记录:正常请求记录 info,慢请求记录 warning 或 critical
  3. 关注 95/99 分位值:比平均值更有参考价值
  4. 关联上下文:记录用户ID、版本号等便于定位问题
  5. 定期清理:数据库记录要定期归档或删除

选择哪种方式取决于你的具体需求,个人推荐中间件 + Telescope的组合,既能精细控制,又有可视化界面。

抱歉,评论功能暂时关闭!