本文目录导读:

我来介绍几种在 Laravel 中通过中间件实现请求日志记录的方法:
创建日志中间件
php artisan make:middleware RequestLogger
基础版本实现
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
class RequestLogger
{
/**
* 处理请求
*/
public function handle(Request $request, Closure $next)
{
// 请求前记录
$startTime = microtime(true);
$response = $next($request);
// 请求后记录
$duration = microtime(true) - $startTime;
$this->logRequest($request, $response, $duration);
return $response;
}
/**
* 记录请求日志
*/
protected function logRequest($request, $response, $duration)
{
$logData = [
'method' => $request->method(),
'url' => $request->fullUrl(),
'ip' => $request->ip(),
'user_agent' => $request->userAgent(),
'status' => $response->status(),
'duration' => round($duration * 1000, 2) . 'ms',
'timestamp' => now()->toDateTimeString(),
];
// 记录到日志文件
Log::channel('request_log')->info('Request Log', $logData);
}
}
配置日志通道
在 config/logging.php 中添加专门通道:
'channels' => [
'request_log' => [
'driver' => 'daily',
'path' => storage_path('logs/requests/request.log'),
'level' => 'info',
'days' => 30,
'formatter' => Monolog\Formatter\LineFormatter::class,
'formatter_with' => [
'format' => "[%datetime%] %message% %context%\n",
],
],
],
高级版本(支持数据库记录)
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use App\Models\RequestLog;
use Illuminate\Support\Str;
class AdvancedRequestLogger
{
// 需要排除的路径
protected $excludedPaths = [
'livewire/*',
'telescope/*',
'horizon/*',
'_debugbar/*',
];
// 敏感字段(记录时需隐藏)
protected $sensitiveFields = [
'password',
'password_confirmation',
'token',
'secret',
];
public function handle(Request $request, Closure $next)
{
// 检查是否需要排除
if ($this->shouldExclude($request)) {
return $next($request);
}
$startTime = microtime(true);
$requestId = (string) Str::uuid();
// 添加请求ID到请求头
$request->headers->set('X-Request-Id', $requestId);
$response = $next($request);
$duration = microtime(true) - $startTime;
$this->logRequest($request, $response, $duration, $requestId);
// 添加响应头
$response->headers->set('X-Request-Id', $requestId);
$response->headers->set('X-Response-Time', round($duration * 1000, 2) . 'ms');
return $response;
}
protected function logRequest($request, $response, $duration, $requestId)
{
$requestData = $request->all();
$this->hideSensitiveData($requestData);
$logData = [
'request_id' => $requestId,
'method' => $request->method(),
'url' => $request->fullUrl(),
'ip' => $request->ip(),
'user_agent' => $request->userAgent(),
'user_id' => auth()->id(),
'headers' => $this->getRelevantHeaders($request),
'input_data' => $requestData,
'response_status' => $response->status(),
'response_body' => $this->getResponseBody($response),
'duration' => round($duration * 1000, 2),
'memory_usage' => memory_get_peak_usage(true) / 1024 / 1024 . 'MB',
];
// 记录到文件
Log::channel('request_log')->info('API Request', $logData);
// 可选:记录到数据库
try {
RequestLog::create($logData);
} catch (\Exception $e) {
Log::error('Failed to save request log to database', ['error' => $e->getMessage()]);
}
}
protected function shouldExclude($request)
{
foreach ($this->excludedPaths as $pattern) {
if ($request->is($pattern)) {
return true;
}
}
return false;
}
protected function hideSensitiveData(&$data)
{
foreach ($data as $key => &$value) {
if (in_array($key, $this->sensitiveFields)) {
$value = '******';
}
}
}
protected function getRelevantHeaders($request)
{
$relevantHeaders = [
'content-type',
'accept',
'authorization',
'x-requested-with',
];
$headers = [];
foreach ($relevantHeaders as $header) {
if ($value = $request->header($header)) {
$headers[$header] = $header === 'authorization' ? '******' : $value;
}
}
return $headers;
}
protected function getResponseBody($response)
{
$content = $response->getContent();
// 限制响应体大小
if (strlen($content) > 10000) {
return substr($content, 0, 10000) . '...';
}
return $content;
}
}
创建数据库模型
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class RequestLog extends Model
{
protected $fillable = [
'request_id',
'method',
'url',
'ip',
'user_agent',
'user_id',
'headers',
'input_data',
'response_status',
'response_body',
'duration',
'memory_usage',
];
protected $casts = [
'headers' => 'array',
'input_data' => 'array',
];
// 按用户范围查询
public function scopeByUser($query, $userId)
{
return $query->where('user_id', $userId);
}
// 按状态码查询
public function scopeByStatus($query, $status)
{
return $query->where('response_status', $status);
}
}
注册中间件
在 app/Http/Kernel.php 中注册:
protected $middlewareGroups = [
'web' => [
// ... 其他中间件
\App\Http\Middleware\RequestLogger::class, // 基础版本
// \App\Http\Middleware\AdvancedRequestLogger::class, // 高级版本
],
'api' => [
// ... 其他中间件
\App\Http\Middleware\AdvancedRequestLogger::class,
],
];
// 或者注册为路由中间件
protected $routeMiddleware = [
// ... 其他中间件
'log.request' => \App\Http\Middleware\RequestLogger::class,
];
使用示例
在路由中使用:
// 应用到整个路由组
Route::middleware(['log.request'])->group(function () {
Route::get('/users', [UserController::class, 'index']);
Route::post('/users', [UserController::class, 'store']);
});
// 应用到单个路由
Route::get('/special-page', [PageController::class, 'show'])
->middleware('log.request');
查看日志:
# 查看日志文件
tail -f storage/logs/requests/request-2024-01-01.log
# 查询数据库
DB::table('request_logs')
->where('response_status', '>=', 500)
->orderBy('created_at', 'desc')
->get();
优化建议
// 1. 异步记录日志(使用队列)
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
class LogRequestJob implements ShouldQueue
{
use Queueable, Dispatchable, InteractsWithQueue, SerializesModels;
public function handle($logData)
{
// 处理日志记录
}
}
// 2. 使用事件系统
Event::listen('request.logged', function ($logData) {
// 发送到外部日志系统
});
// 3. 条件记录
if (config('app.log_requests')) {
$this->logRequest($request, $response, $duration);
}
这样实现后,你的 Laravel 应用就会自动记录所有请求的详细信息,便于调试、监控和审计。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播