核心是暴露格式正确的/metrics路由且复用单例CollectorRegistry;否则Prometheus抓空或报错。常见500因observe传null/非法标签,响应头须为Content-Type: text/plain; version=0.0.4,指标耗时用Gauge、计数用Counter,Nginx需alias直连控制器。

Webman 要让 Prometheus 抓到真实、稳定、可画图的指标,核心就两件事:暴露一个格式正确的 /metrics 路由,且所有指标必须注册在同一个 CollectorRegistry 实例上——漏掉任一,Prometheus 就会抓空或报错。
为什么 /metrics 返回 500 或空内容
最常见原因是指标更新逻辑里抛了未捕获异常,比如在中间件中调用 $gauge->observe($duration) 时传入了 null 或负数,或者标签值含空格、斜杠等非法字符。Prometheus 客户端不兜底这些 PHP 错误,render() 会直接中断并返回 500。
- 检查
app/controller/MetricsController.php的index()方法:必须先调用$registry->render(),不能漏掉或放在 try/catch 外围 - 响应头必须严格为
Content-Type: text/plain; version=0.0.4,少分号、写成v0.0.4或多加空格都会导致 Prometheus 标记为 INVALID - 上线前务必用
curl -v http://your-domain.com/metrics验证:响应体应为纯文本,以# HELP开头,每行形如webman_http_requests_total{method="GET",status="200"} 123
如何避免多 Worker 进程下指标混乱
Webman 默认启动多个 Worker 进程,如果每个进程都独立 new CollectorRegistry,Prometheus 抓到的就是 N 份重复指标:Counter 值跳变、Gauge 时间序列错乱、图表完全不可信。
Webman 2.2.0版本强化了 TCP/UDP 服务支持,优化路由组管理,并增强异步任务处理能力。结合协程与连接池技术,Webman 能轻松应对高并发场景,适用于网站、接口服务、即时通讯、物联网及游戏开发,兼具高性能、灵活扩展与稳定可靠,是多场景 PHP 服务开发的理想选择。
-
CollectorRegistry初始化只能做一次,必须放在app/Bootstrap.php中,绑定到Container或设为全局静态属性 - 不要在中间件构造函数或
handle()里初始化 registry;也不要在每次请求中new CollectorRegistry() - 定义指标(如
$counter = $registry->getOrRegisterCounter(...))可以多次调用,但底层 registry 实例必须唯一
该用 Gauge 还是 Counter 记录 HTTP 耗时
HTTP 请求耗时必须用 Gauge(如 webman_http_request_duration_seconds),不能用 Counter。Counter 只适合累加计数,而耗时是瞬时观测值,需要被 observe() 写入当前采样点。
-
Counter适用场景:请求数(webman_http_requests_total)、错误次数、登录失败数 -
Gauge适用场景:当前内存占用、活跃 WebSocket 连接数、单次请求耗时(单位秒,浮点) - 在全局中间件(如
app/middleware/RequestLog.php)的after()钩子中调用:$gauge->observe($duration, ['route' => $route]),确保请求结束才写入
Nginx 配置 /metrics 路由的常见陷阱
别用 root + index,Nginx 会尝试加载 /metrics/index.php 导致 404;必须用 alias 指向控制器文件的完整物理路径。
- 正确写法:
location /metrics { alias /var/www/my-webman/app/controller/MetricsController.php; fastcgi_pass 127.0.0.1:9000; ... } -
alias后路径必须是绝对路径,结尾不加/,且该 PHP 文件需有读权限 -
/metrics响应必须轻量:禁止数据库查询、Redis 调用、文件 IO;所有指标数据应在内存中完成聚合
真正难的不是“怎么加指标”,而是保证所有 Worker 进程共享同一套指标状态,并让每行输出都严格符合 OpenMetrics 文本格式——格式错一个字符,Prometheus 就不会入库。别指望自动修复,得手动 curl 验证每一行。


















