Метрики Prometheus

OxPHP отдаёт Prometheus-совместимые метрики в текстовом формате экспозиции (text exposition format) на GET /metrics внутреннего сервера. Они охватывают пропускную способность по запросам, время ответа, состояние соединений, состояние пула воркеров, кеширование статических файлов, эффективность сжатия и производительность режима воркеров.

Включение метрик

Задайте INTERNAL_ADDR, чтобы запустить внутренний сервер:

bash
INTERNAL_ADDR=127.0.0.1:9090

Затем собирайте метрики из Prometheus или любого совместимого коллектора:

bash
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). Экспортируется всегда
Note

Экспортируются только методы и классы статусов, по которым зафиксировано хотя бы одно событие. Метки с нулевым значением опускаются.

Гистограмма длительности запросов

Метрика Тип Описание
oxphp_request_duration_us histogram Полная длительность запроса в микросекундах для всех запросов (статические файлы и PHP)

Границы бакетов (микросекунды): 100, 500, 1000, 2500, 5000, 10000, 25000, 50000, 100000, 250000, 500000, 1000000, +Inf.

Используйте эту гистограмму, чтобы отслеживать общую задержку, выявлять медленные эндпоинты и измерять перцентили хвостовой задержки (tail latency).

Метрики соединений

Метрика Тип Описание
oxphp_active_connections gauge Открытые в данный момент TCP-соединения на основном порту
oxphp_pending_requests gauge PHP-запросы, принятые, но ещё не отвеченные — ждущие слота очереди, стоящие в очереди или выполняющиеся. Только запросы, направленные в PHP: статический файл, 404 или запрещённый путь получают ответ без очереди и здесь никогда не появляются
oxphp_dropped_requests_total counter Запросы, при которых PHP-воркер завершился с ошибкой уже после приёма запроса
oxphp_admission_refused_total counter Запросы, получившие ответ, так и не добравшись до воркера. Метка: reasonwait_timeout (прождал весь QUEUE_WAIT_TIMEOUT_MS, дайте пулу больше запаса), waiting_full (уже ждут QUEUE_MAX_WAITING запросов, поднимите его или MAX_CONNECTIONS), waiting_bytes (уже припаркованные тела заполнили QUEUE_MAX_WAITING_BYTES, и телу этого запроса негде было разместиться — поднимите его или уменьшите, сколько клиенту позволено загружать), queue_full (QUEUE_WAIT_TIMEOUT_MS=0, ожидание выключено), shutting_down (крайний срок слива истёк, пока запрос ещё ждал допуска), pool_unavailable (не осталось потока воркера, которому можно передать запрос, — пул исчез, а не занят). Только первые четыре причины — перегрузка, и они отвечают 529; shutting_down отвечает 503, как и остальной корректный слив, а pool_unavailable отвечает 500. Оповещайте о перегрузке именно по этим четырём: метрика в целом растёт и при перезапуске. Не входит в oxphp_queue_wait_us

Метрики пула воркеров

Метрика Тип Описание
oxphp_workers_current gauge Текущее число потоков PHP-воркеров
oxphp_workers_min gauge Минимальное число воркеров (в статическом режиме равно текущему)
oxphp_workers_max gauge Максимальное число воркеров (в статическом режиме равно текущему)
oxphp_workers_idle gauge Потоки воркеров без запросов в обработке; вычисляется как workers_current - busy_workers
oxphp_busy_workers gauge Потоки воркеров, выполняющие в данный момент хотя бы один запрос; никогда не превышает oxphp_workers_current. Считает потоки, а не запросы — в режиме воркеров один поток мультиплексирует много файберов запросов и всё равно считается один раз. Запросы, ждущие допуска или стоящие в очереди, не учитываются; они видны в oxphp_pending_requests
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, 100000, 250000, 500000, 1000000, +Inf.

Здесь измеряется время, проведённое в ожидании — сначала допуска, затем в очереди — за вычетом времени выполнения самого скрипта, так что метрика отвечает на вопрос «сколько прошло, прежде чем воркер это забрал», а не «сколько занял запрос». Запросы, отклонённые с 529, в очередь так и не попали и здесь не записываются; считайте их через oxphp_admission_refused_total.

Большое время ожидания в очереди указывает на то, что все воркеры заняты и вам следует увеличить PHP_WORKERS. Диапазон доходит до одной секунды, совпадая с QUEUE_WAIT_TIMEOUT_MS по умолчанию, поэтому запрос, потративший перед выполнением большую часть своего бюджета ожидания, получает численную оценку, а не сваливается в +Inf. Ничто из обслуженного не ждёт дольше бюджета — за его пределами запрос отклоняется, — так что повышение QUEUE_WAIT_TIMEOUT_MS — единственная настройка, возвращающая ожидания в +Inf.

Метрики ограничения частоты запросов

Метрика Тип Описание
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 Всего мягких сбросов, выполненных между запросами

Датчики по отдельным воркерам

Метрика Тип Описание
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 появляются, как только пул подключит свой счётчик задач в обработке, а 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-запросы полезны при построении дашбордов:

Частота запросов (запросов в секунду):

text
rate(oxphp_requests_total[5m])

Среднее время ответа (миллисекунды):

text
rate(oxphp_request_duration_us_sum[5m]) / rate(oxphp_requests_total[5m]) / 1000

p99 длительности запроса (миллисекунды):

text
histogram_quantile(0.99, rate(oxphp_request_duration_us_bucket[5m])) / 1000

Доля ошибок (ответы 5xx в процентах):

text
rate(oxphp_responses_by_status_total{status="5xx"}[5m]) / rate(oxphp_requests_total[5m]) * 100

Загрузка пула воркеров:

text
oxphp_busy_workers / oxphp_workers_current

Это настоящая доля между 0 и 1. Устойчивые значения на уровне 1 означают, что каждый воркер занят и вновь прибывающие запросы встают в очередь. Сопоставляйте её с rate(oxphp_admission_refused_total{reason=~"queue_full|wait_timeout|waiting_full|waiting_bytes"}[5m]), чтобы видеть, превращается ли этот затор в отказы, и с oxphp_pending_requests, чтобы видеть, насколько он глубок.

Насыщение очереди (частота отбрасывания в секунду):

text
rate(oxphp_dropped_requests_total[5m])

p99 ожидания в очереди (микросекунды):

text
histogram_quantile(0.99, rate(oxphp_queue_wait_us_bucket[5m]))

Доля попаданий в кеш статических файлов:

text
rate(oxphp_static_cache_hits_total[5m]) / (rate(oxphp_static_cache_hits_total[5m]) + rate(oxphp_static_cache_misses_total[5m]))

Байты, сэкономленные сжатием, в секунду:

text
rate(oxphp_compression_bytes_saved_total[5m])

p99 задержки в режиме воркеров (микросекунды):

text
histogram_quantile(0.99, rate(oxphp_worker_request_duration_us_bucket[5m]))

Частота перезапусков воркеров (в минуту):

text
rate(oxphp_worker_recycles_total[5m]) * 60

Среднее использование памяти воркером:

text
avg(oxphp_worker_memory_bytes)

Конфигурация сбора для Prometheus

Добавьте задание сбора (scrape job) в ваш prometheus.yml:

prometheus.yml
scrape_configs: - job_name: "oxphp" scrape_interval: 15s static_configs: - targets: ["oxphp:9090"]

Для service discovery в Kubernetes:

prometheus.yml
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"

Смотрите также

Нашли ошибку? Сообщите →