必须将限流行为转为可观测指标,通过监听ThrottleRequestsException事件、配置专用日志通道、用Redis聚合拦截计数(推荐按路由+分钟级key),并集成Prometheus暴露laravel_throttle_hits_total指标。

要实时知道哪些接口被限流拦截、谁触发了拦截、每分钟拦了多少次,不能只靠日志grep或手动查缓存——必须把限流行为变成可观测指标,直接暴露在监控面板里。
启用 Laravel RateLimiter 的事件监听
第一步:在 app/Providers/AppServiceProvider.php 的 boot() 方法中注册限流触发事件监听器。
RateLimiter::hit() 本身不发事件,但 Laravel 在 throttle 中间件抛出 ThrottleRequestsException 时会触发 Illuminate\Routing\Events\RouteMatched 之后的异常处理链,所以真正可靠的方式是监听异常。
添加如下代码:
use Illuminate\Http\Exceptions\ThrottleRequestsException;use Illuminate\Support\Facades\Event;Event::listen(ThrottleRequestsException::class, function ($event) { Log::channel('throttle')->info('Rate limit hit', [ 'key' => $event->getKey(), 'max_attempts' => $event->getMaxAttempts(), 'decay_seconds' => $event->getDecaySeconds(), 'ip' => request()->ip(), 'user_id' => auth()->id() ?: null, 'route_name' => request()->route()?->getName(), ]);});
注意:这个监听必须放在 boot() 早期,且不能依赖任何尚未注册的服务(如 DB),否则在高并发下可能引发启动失败。
配置专用限流日志通道
编辑 config/logging.php,在 'channels' 数组中新增一个名为 'throttle' 的 daily 日志通道:
'throttle' => [ 'driver' => 'daily', 'path' => storage_path('logs/throttle.log'), 'level' => 'info', 'days' => 7, 'tap' => [App\Logging\EnsureThrottleDir::class],],
这一步确保限流日志不混入 main.log,避免干扰常规错误排查。storage/logs/throttle.log 文件将自动按天轮转,保留最近 7 天数据。
如果目录不存在,Laravel 不会自动创建;务必提前运行 mkdir -p storage/logs,否则首次写入会静默失败。
用 Redis 实时聚合拦截计数
方法一:在事件监听器内直接 incr 计数器
把上面 Event::listen 块里的 Log::channel(...) 替换为:
$key = 'throttle:count:' . now()->format('Y-m-d:H');Cache::store('redis')->increment($key);
这样每小时生成一个 key,例如 throttle:count:2026-08-06:10,值就是该小时被拦截总次数。
方法二:按接口维度拆分统计(推荐)
改用更细粒度的 key:
$route = request()->route()?->getName() ?: 'fallback';$key = 'throttle:by-route:' . $route . ':' . now()->format('Y-m-d:H:i');Cache::store('redis')->increment($key, 1);
这个 key 每分钟刷新一次,支持按 route name + 分钟级精度查询。比如查 api.v1.users.index 过去 5 分钟被拦多少次,直接 getrange 就能拿到。
注意:不要用 $request->url() 作为 key 的一部分——带 query 参数的 URL 会导致 key 爆炸式增长,应始终优先使用 route name 或自定义策略名(如 api-by-device)。
暴露 Prometheus 指标端点
第一步:安装 laravel-prometheus-exporter 包
composer require nunomaduro/laravel-prometheus-exporter
第二步:发布配置并启用中间件
php artisan vendor:publish --provider="NunoMaduro\LaravelPrometheusExporter\Providers\PrometheusExporterServiceProvider"
第三步:在 app/Http/Kernel.php 的 $middlewareGroups['api'] 中加入:
\NunoMaduro\LaravelPrometheusExporter\Middleware\PrometheusExporterMiddleware::class
第四步:在事件监听器中注入指标收集器
修改 AppServiceProvider 中的监听逻辑:
use NunoMaduro\LaravelPrometheusExporter\Metrics\Counter;Counter::name('laravel_throttle_hits_total') ->labels(['route' => $route ?: 'unknown', 'key_type' => $event->getKey() ? 'custom' : 'default']) ->inc();
访问 /metrics 即可看到形如 laravel_throttle_hits_total{route="api.v1.login",key_type="custom"} 42 的原始指标行,Grafana 可直接接入。


















