PHP 与 Laravel 应用接入 Prometheus 监控

PHP/Laravel 接入 Prometheus 监控:promphp/prometheus_client_php 客户端、Counter/Gauge/Histogram 埋点、存储后端选择(Redis/APCu)、Laravel 中间件集成与 FAQ。

最佳实践
PHP 与 Laravel 应用接入 Prometheus 监控技术指南封面

PHP 的请求模型(每请求一个进程生命周期,FPM 下尤其明显)让它的指标埋点有些特殊——指标必须落到一个跨请求共享的存储里。本文讲清正确姿势。

安装客户端

composer require promphp/prometheus_client_php

关键差异:指标存储后端

Go/Java 的指标存在进程内存里,而 PHP-FPM 每个请求结束进程状态就重置。客户端库需要外部存储:

use Prometheus\Storage\Redis;
use Prometheus\CollectorRegistry;

// 生产推荐 Redis(跨进程共享)
Redis::setDefaultOptions(['host' => '127.0.0.1', 'port' => 6379]);
$registry = new CollectorRegistry(Redis::getDefault());

// 测试/单机可用 APCu
// $registry = new CollectorRegistry(new \Prometheus\Storage\APCu());

埋点三种指标

// Counter:请求总数
$counter = $registry->getOrRegisterCounter('app', 'http_requests_total',
    'Total HTTP requests', ['method', 'route', 'status']);
$counter->inc(['GET', '/api/users', '200']);

// Gauge:瞬时值(当前活跃请求、内存占用)
$gauge = $registry->getOrRegisterGauge('app', 'memory_usage_bytes', 'Memory usage');
$gauge->set(memory_get_usage(true));

// Histogram:延迟分布
$hist = $registry->getOrRegisterHistogram('app', 'request_duration_seconds',
    'Request duration', ['route'], [0.01, 0.05, 0.1, 0.5, 1, 5]);
$hist->observe($duration, ['/api/users']);

暴露 /metrics 端点

// routes/web.php 或独立入口
Route::get('/metrics', function () {
    $registry = new CollectorRegistry(Redis::getDefault());
    $renderer = new \Prometheus\RenderTextFormat();
    return response($renderer->render($registry->getMetricFamilySamples()))
        ->header('Content-Type', 'text/plain; version=0.0.4');
});

Laravel 中间件统一采集

class PrometheusMiddleware
{
    public function handle($request, Closure $next)
    {
        $start = microtime(true);
        $response = $next($request);

        $route = $request->route()?->uri() ?? 'unknown';   // 路由模板,不是原始 URL
        $registry = new CollectorRegistry(Redis::getDefault());

        $registry->getOrRegisterCounter('app', 'http_requests_total', '', ['method','route','status'])
            ->inc([$request->method(), $route, $response->getStatusCode()]);

        $registry->getOrRegisterHistogram('app', 'request_duration_seconds', '', ['route'])
            ->observe(microtime(true) - $start, [$route]);

        return $response;
    }
}

$route 务必用路由模板——用 $request->path() 会把 /users/123 这种 ID 路径变成基数炸弹。

观测云对照

PHP 应用更完整的路径是观测云 APM 探针:无需手写埋点即可获得请求速率、错误率、延迟分布、慢事务与数据库调用分解;自定义业务指标照走 Prometheus 端点由 DataKit 抓取汇聚,两套数据在同一平台关联。FPM 特有指标(活跃进程、队列长度)也有现成的 PHP-FPM 集成。

常见问题(FAQ)

Q:为什么指标值重启 FPM 后还在?
A:因为存在 Redis/APCu 里——这正是目的。注意这意味着需要手动清理过期序列(长期不再出现的标签组合),客户端库提供 wipeStorage() 之类的能力,建议在发布流程里定期清。

Q:APCu 和 Redis 怎么选?
A:单机部署 APCu 零依赖;多机部署必须 Redis(否则 Prometheus 每次抓到的是不同机器的部分数据)。

Q:CLI/队列任务(Artisan command、Horizon)怎么埋点?
A:同样写 Redis 存储即可,/metrics 端点由 Web 进程统一渲染——Web 与 CLI 共享 Redis 存储是这套架构成立的关键。

获取专属方案

联系我们

加入社区

微信扫码
加入官方交流群

立即体验

在线开通,按量计费,真正的云服务!

立即开始

选择观测云版本

代码托管平台