Prometheus 指标
OxPHP 在内部服务器的 GET /metrics 上以文本展示格式暴露 Prometheus 兼容指标。它们涵盖请求吞吐量、响应时间、连接状态、工作进程池健康状况、静态文件缓存、压缩效率以及工作进程模式的性能。
启用指标
设置 INTERNAL_ADDR 以启动内部服务器:
INTERNAL_ADDR=127.0.0.1:9090然后从 Prometheus 或任何兼容的采集器进行抓取:
curl http://localhost:9090/metrics服务器指标
| 指标 | 类型 | 说明 |
|---|---|---|
oxphp_uptime_seconds |
gauge | 服务器进程启动以来的秒数 |
oxphp_requests_total |
counter | 主端口上接收到的 HTTP 请求总数 |
请求指标
| 指标 | 类型 | 说明 |
|---|---|---|
oxphp_requests_by_method_total |
counter | 按 HTTP 方法统计的请求数。标签:method(GET、POST、PUT、DELETE、PATCH、HEAD、OPTIONS、CONNECT、QUERY、OTHER) |
oxphp_responses_by_status_total |
counter | 按状态类别统计的响应数。标签:status(1xx、2xx、3xx、4xx、5xx) |
oxphp_request_bytes_total |
counter | 接收到的请求体字节总数 |
oxphp_response_bytes_total |
counter | 发送的响应体字节总数 |
oxphp_request_cancelled_total |
counter | 按原因统计的已取消请求数。标签:reason(client_abort、timeout、shutdown)。始终输出 |
只有至少记录过一次事件的方法和状态类别才会被输出。计数为零的标签会被省略。
请求耗时直方图
| 指标 | 类型 | 说明 |
|---|---|---|
oxphp_request_duration_us |
histogram | 所有请求(静态文件和 PHP)的端到端请求耗时,单位为微秒 |
分桶边界(微秒):100、500、1000、2500、5000、10000、25000、50000、100000、250000、500000、1000000、+Inf。
使用该直方图可以跟踪整体延迟、识别慢端点,并测量尾部延迟百分位数。
连接指标
| 指标 | 类型 | 说明 |
|---|---|---|
oxphp_active_connections |
gauge | 主端口上当前打开的 TCP 连接数 |
oxphp_pending_requests |
gauge | 当前已分发给 PHP 工作进程的请求(排队中及处理中) |
oxphp_dropped_requests_total |
counter | PHP 工作进程在接受请求后处理失败的请求数 |
工作进程池指标
| 指标 | 类型 | 说明 |
|---|---|---|
oxphp_workers_current |
gauge | 当前 PHP 工作进程线程数 |
oxphp_workers_min |
gauge | 最小工作进程数(在静态模式下等于当前数量) |
oxphp_workers_max |
gauge | 最大工作进程数(在静态模式下等于当前数量) |
oxphp_workers_idle |
gauge | 当前未处理请求的工作进程数 |
oxphp_busy_workers |
gauge | 当前正在处理请求的工作进程数 |
oxphp_workers_spawned_total |
counter | 自启动以来创建的工作进程总数(含初始工作进程) |
oxphp_workers_retired_total |
counter | 因空闲超时而退役的工作进程总数(仅限动态模式) |
工作进程监督器指标
由工作进程监督器输出的按工作进程粒度的可观测性数据。每条时间序列都带有 worker_id 标签(槽位索引)。一旦监督器开始跟踪按工作进程的状态,这些指标便会出现。
| 指标 | 类型 | 说明 |
|---|---|---|
oxphp_worker_request_age_seconds |
gauge | 每个工作进程上处理中请求的存活时长,单位为秒。标签:worker_id |
oxphp_worker_long_running_total |
counter | 监督器扫描时观察到请求存活时间超过卡住阈值的次数。标签:worker_id |
oxphp_worker_stuck_total |
counter | 每个工作进程的卡住分类计数器。标签:worker_id、kind(io、c_call、cpu) |
队列等待直方图
| 指标 | 类型 | 说明 |
|---|---|---|
oxphp_queue_wait_us |
histogram | 请求在被工作进程取走之前于队列中等待的时长,单位为微秒 |
分桶边界(微秒):50、100、250、500、1000、2500、5000、10000、50000、+Inf。
较高的队列等待时间表明所有工作进程都处于繁忙状态,你应当调高 PHP_WORKERS 或 QUEUE_CAPACITY。
限流指标
| 指标 | 类型 | 说明 |
|---|---|---|
oxphp_rate_limited_total |
counter | 被限流器拒绝的请求数(返回 429) |
oxphp_php_deny_total |
counter | 被 PHP_DENY_PATHS 拦截的请求数(.php 执行被拒绝)。参见 PHP 执行拒绝列表 |
静态文件缓存指标
| 指标 | 类型 | 说明 |
|---|---|---|
oxphp_static_cache_hits_total |
counter | 由内存缓存提供服务的静态文件请求数 |
oxphp_static_cache_misses_total |
counter | 需要从磁盘读取的静态文件请求数 |
压缩指标
| 指标 | 类型 | 说明 |
|---|---|---|
oxphp_compressed_responses_total |
counter | 使用 Brotli 压缩的响应数 |
oxphp_compression_bytes_saved_total |
counter | 压缩节省的字节总数(原始大小减去压缩后大小) |
工作进程模式指标
这些指标仅在工作进程模式激活时(WORKER_MODE_ENABLED=true)才会输出。
全局计数器
| 指标 | 类型 | 说明 |
|---|---|---|
oxphp_worker_mode_enabled |
gauge | 工作进程模式激活时始终为 1 |
oxphp_worker_requests_handled_total |
counter | 常驻工作进程处理的请求总数 |
oxphp_worker_recycles_total |
counter | 工作进程回收总数(工作进程退出并被重新创建) |
oxphp_worker_recycles_by_reason_total |
counter | 按原因统计的回收次数。标签:reason(scheduled、max_memory、error) |
oxphp_worker_soft_resets_total |
counter | 在两次请求之间执行的软重置总数 |
按工作进程的 gauge
| 指标 | 类型 | 说明 |
|---|---|---|
oxphp_worker_memory_bytes |
gauge | 每个工作进程当前的 PHP 堆使用量。标签:worker(槽位索引,例如 "0"、"1") |
oxphp_worker_uptime_seconds |
gauge | 每个工作进程被创建以来的秒数。标签:worker |
oxphp_worker_requests_count |
gauge | 每个工作进程实例处理的请求数。标签:worker |
工作进程请求耗时直方图
| 指标 | 类型 | 说明 |
|---|---|---|
oxphp_worker_request_duration_us |
histogram | 每个请求的 PHP 处理器执行时间,单位为微秒(仅限工作进程模式) |
分桶边界(微秒):100、250、500、1000、2500、5000、10000、25000、50000、+Inf。
该直方图测量的是在 PHP 处理器回调内部花费的时间,不包含队列等待时间。可用它来识别慢处理器,并在工作进程模式下跟踪尾部延迟。
异步池指标
这些指标需要将 ASYNC_WORKERS 设为非零值,并且每项都有各自的输出门槛:计数器仅在至少有一个任务被分发或被拒绝后才会出现,_in_flight / _in_flight_limit gauge 在池连接好其处理中计数器后出现,而 oxphp_async_output_discarded_bytes_total 仅在有部分输出被丢弃后才会出现。
| 指标 | 类型 | 说明 |
|---|---|---|
oxphp_async_tasks_dispatched_total |
counter | 分发给后台池的异步任务总数 |
oxphp_async_tasks_completed_total |
counter | 成功完成的异步任务数 |
oxphp_async_tasks_failed_total |
counter | 抛出异常的异步任务数 |
oxphp_async_tasks_cancelled_total |
counter | 被取消的异步任务数 |
oxphp_async_tasks_rejected_total |
counter | 在分发时被拒绝的异步任务数——因为池队列已满或达到处理中上限(ASYNC_MAX_FIBERS × ASYNC_WORKERS) |
oxphp_async_tasks_stranded_total |
counter | 超过 await_race / await_any 超时后仍在运行的工作进程。每个滞留任务最多可将 RSHUTDOWN 延长 5 秒。 |
oxphp_async_tasks_in_flight |
gauge | 当前排队或运行中的异步任务(在池连接好其处理中计数器后输出) |
oxphp_async_tasks_in_flight_limit |
gauge | 并发异步任务的最大数量(ASYNC_MAX_FIBERS × ASYNC_WORKERS) |
oxphp_async_output_discarded_bytes_total |
counter | 在工作进程空闲时丢弃的异步任务输出字节数(异步任务中的 echo 没有客户端可接收) |
Grafana 仪表盘技巧
以下 PromQL 查询有助于构建仪表盘:
请求速率(每秒请求数):
rate(oxphp_requests_total[5m])平均响应时间(毫秒):
rate(oxphp_request_duration_us_sum[5m])
/ rate(oxphp_requests_total[5m]) / 1000p99 请求耗时(毫秒):
histogram_quantile(0.99, rate(oxphp_request_duration_us_bucket[5m])) / 1000错误率(5xx 响应的百分比):
rate(oxphp_responses_by_status_total{status="5xx"}[5m])
/ rate(oxphp_requests_total[5m]) * 100工作进程池利用率:
oxphp_busy_workers / oxphp_workers_current队列饱和度(每秒丢弃率):
rate(oxphp_dropped_requests_total[5m])p99 队列等待时间(微秒):
histogram_quantile(0.99, rate(oxphp_queue_wait_us_bucket[5m]))静态文件缓存命中率:
rate(oxphp_static_cache_hits_total[5m])
/ (rate(oxphp_static_cache_hits_total[5m]) + rate(oxphp_static_cache_misses_total[5m]))每秒因压缩节省的字节数:
rate(oxphp_compression_bytes_saved_total[5m])工作进程模式 p99 延迟(微秒):
histogram_quantile(0.99, rate(oxphp_worker_request_duration_us_bucket[5m]))工作进程回收速率(每分钟):
rate(oxphp_worker_recycles_total[5m]) * 60工作进程平均内存使用量:
avg(oxphp_worker_memory_bytes)Prometheus 抓取配置
在你的 prometheus.yml 中添加一个抓取任务:
scrape_configs:
- job_name: "oxphp"
scrape_interval: 15s
static_configs:
- targets: ["oxphp:9090"]对于 Kubernetes 服务发现:
scrape_configs:
- job_name: "oxphp"
kubernetes_sd_configs:
- role: pod
relabel_configs:
- source_labels: [__meta_kubernetes_pod_label_app]
regex: oxphp
action: keep
- source_labels: [__meta_kubernetes_pod_ip]
target_label: __address__
replacement: "$1:9090"