php应用必须通过/metrics端点手动输出严格符合prometheus文本协议的指标:每行以# help、# type或指标名开头,标签值用双引号包裹并转义,响应头为text/plain; version=0.0.4,禁止空格/html/json,避免库自动输出缺陷。

PHP 应用本身不直接暴露 Prometheus 格式指标,必须通过独立的 metrics 端点(如 /metrics)返回文本格式数据,且需严格遵循 Prometheus 文本协议规范,否则 prometheus 服务端抓取会失败或解析出错。
如何让 PHP 输出合法的 Prometheus metrics 文本
关键不是“生成指标”,而是“按协议输出”。Prometheus 要求每行以 # HELP、# TYPE 或指标名开头,指标名后跟大括号标签、空格、数值、可选时间戳。PHP 不能依赖第三方库“自动处理一切”——很多轻量库(如 promphp/promphp)默认不加 # TYPE 行,或把标签顺序搞乱,导致 scrape_series_added 为 0。
推荐手动构造(更可控):
header('Content-Type: text/plain; version=0.0.4');
echo "# HELP php_api_up Whether the API is up (1) or down (0)\n";
echo "# TYPE php_api_up gauge\n";
echo "php_api_up{env=\"prod\",service=\"user-api\"} " . (is_api_healthy() ? '1' : '0') . "\n";
echo "# HELP php_api_response_time_seconds API response time in seconds\n";
echo "# TYPE php_api_response_time_seconds histogram\n";
echo "php_api_response_time_seconds_bucket{le=\"0.1\",env=\"prod\"} 124\n";
echo "php_api_response_time_seconds_bucket{le=\"0.2\",env=\"prod\"} 189\n";
echo "php_api_response_time_seconds_sum{env=\"prod\"} 28.45\n";
echo "php_api_response_time_seconds_count{env=\"prod\"} 189\n";
-
is_api_healthy()应包含真实探活逻辑(如连 DB、查健康接口),不能只返回true - 所有指标名、标签键必须是 ASCII 字符,标签值需用双引号包裹,内部双引号要转义为
\" - 避免在指标行末尾加空格或制表符,
prometheus抓取器对空白敏感
为什么用 curl 或 file_sd_configs 都无法替代真实端点
有人试图绕过 PHP 暴露端点,改用 curl 定时调用 API 再写入文件,再让 Prometheus 用 textfile_collector 读——这会导致指标延迟高、时间戳不准、且无法体现瞬时状态(如某次请求超时)。更重要的是:textfile_collector 只支持静态文件,不支持动态标签(如按 host 区分多实例)。
正确做法是让每个 PHP 实例独立暴露 /metrics,Prometheus 通过服务发现(如 Consul、DNS SRV)或静态配置直连:
scrape_configs:
- job_name: 'php-api'
static_configs:
- targets: ['10.0.1.10:8080', '10.0.1.11:8080']
labels:
env: prod
service: user-api
- PHP 进程需监听非 80 端口(如
8080),避免与 Web 服务器端口冲突 - 若用 Nginx/Apache,必须显式允许
/metrics路由透传,不能被重写或拦截 - 不要在
/metrics响应中加 HTML、JSON 或其他 Content-Type,text/plain是硬性要求
prometheus_client_php 库的常见陷阱
这个常用库(promphp/promphp)看似开箱即用,但实际部署时高频出问题:
- 默认注册的
Gauge和Counter不带# TYPE行,需手动调用$registry->addCollector($collector)并确保$collector实现了getHelp()和getType() - 标签值含中文、斜杠、空格时,库不会自动转义,直接输出会导致 Prometheus 解析失败(错误:"
expected = after label name") - 它把所有指标塞进一个字符串缓存,高并发下可能因未加锁导致输出错乱(例如两行指标混在一起)
- 不支持直出 OpenMetrics 格式(v1.0.0+),而新版 Prometheus 默认启用 OpenMetrics 解析,建议显式禁用:
enable_open_metrics: false
最稳妥的方式,是只用它做指标收集,自己写一个极简的 /metrics 路由处理器,调用 $registry->render() 后再做一次格式校验(比如检查是否每行都以 # 或字母开头),而不是全盘信任库的输出。
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!











