Métriques Prometheus
OxPHP expose des métriques compatibles Prometheus au format d'exposition texte via GET /metrics sur le serveur interne. Elles couvrent le débit des requêtes, les temps de réponse, l'état des connexions, la santé du pool de workers, la mise en cache des fichiers statiques, l'efficacité de la compression et les performances du mode worker.
Activation des métriques
Définissez INTERNAL_ADDR pour démarrer le serveur interne :
INTERNAL_ADDR=127.0.0.1:9090Ensuite, effectuez le scraping depuis Prometheus ou tout collecteur compatible :
curl http://localhost:9090/metricsMétriques du serveur
| Métrique | Type | Description |
|---|---|---|
oxphp_uptime_seconds |
gauge | Secondes écoulées depuis le démarrage du processus serveur |
oxphp_requests_total |
counter | Total des requêtes HTTP reçues sur le port principal |
Métriques de requêtes
| Métrique | Type | Description |
|---|---|---|
oxphp_requests_by_method_total |
counter | Requêtes par méthode HTTP. Label : method (GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS, CONNECT, QUERY, OTHER) |
oxphp_responses_by_status_total |
counter | Réponses par classe de statut. Label : status (1xx, 2xx, 3xx, 4xx, 5xx) |
oxphp_request_bytes_total |
counter | Total des octets de corps de requête reçus |
oxphp_response_bytes_total |
counter | Total des octets de corps de réponse envoyés |
oxphp_request_cancelled_total |
counter | Requêtes annulées par raison. Label : reason (client_abort, timeout, shutdown). Toujours émise |
Seules les méthodes et classes de statut ayant au moins un événement enregistré sont émises. Les labels à valeur nulle sont omis.
Histogramme de durée de requête
| Métrique | Type | Description |
|---|---|---|
oxphp_request_duration_us |
histogram | Durée de requête de bout en bout en microsecondes pour toutes les requêtes (fichiers statiques et PHP) |
Limites des buckets (microsecondes) : 100, 500, 1000, 2500, 5000, 10000, 25000, 50000, 100000, 250000, 500000, 1000000, +Inf.
Utilisez cet histogramme pour suivre la latence globale, identifier les endpoints lents et mesurer les percentiles de latence de queue.
Métriques de connexion
| Métrique | Type | Description |
|---|---|---|
oxphp_active_connections |
gauge | Connexions TCP actuellement ouvertes sur le port principal |
oxphp_pending_requests |
gauge | Requêtes PHP acceptées mais pas encore répondues — en attente d'une place dans la file, en file, ou en cours d'exécution. Uniquement les requêtes routées vers PHP : un fichier statique, une 404 ou un chemin refusé reçoit sa réponse sans passer par la file et n'apparaît jamais ici |
oxphp_dropped_requests_total |
counter | Requêtes pour lesquelles le worker PHP a échoué après avoir accepté la requête |
oxphp_admission_refused_total |
counter | Requêtes répondues sans atteindre un worker. Label : reason — wait_timeout (a attendu la totalité de QUEUE_WAIT_TIMEOUT_MS, donnez plus de marge au pool), waiting_full (déjà QUEUE_MAX_WAITING requêtes en attente, relevez-le ou relevez MAX_CONNECTIONS), waiting_bytes (les corps déjà stationnés remplissent QUEUE_MAX_WAITING_BYTES, le corps de cette requête n'avait donc nulle part où se poser — relevez-le, ou abaissez ce qu'un client peut téléverser), queue_full (QUEUE_WAIT_TIMEOUT_MS=0, l'attente est désactivée), shutting_down (le délai de drainage a expiré pendant que la requête attendait encore son admission), pool_unavailable (il ne reste aucun thread worker à qui remettre la requête — le pool a disparu, il n'est pas occupé). Seules les quatre premières relèvent de la surcharge et répondent 529 ; shutting_down répond 503 comme le reste du drainage progressif, et pool_unavailable répond 500. Alertez sur la surcharge avec ces quatre-là précisément : la métrique dans son ensemble bouge aussi lors d'un redémarrage. Exclues de oxphp_queue_wait_us |
Métriques du pool de workers
| Métrique | Type | Description |
|---|---|---|
oxphp_workers_current |
gauge | Nombre actuel de threads worker PHP |
oxphp_workers_min |
gauge | Nombre minimal de workers (égal au nombre actuel en mode statique) |
oxphp_workers_max |
gauge | Nombre maximal de workers (égal au nombre actuel en mode statique) |
oxphp_workers_idle |
gauge | Threads worker sans aucune requête en cours, calculé comme workers_current - busy_workers |
oxphp_busy_workers |
gauge | Threads worker exécutant actuellement au moins une requête ; ne dépasse jamais oxphp_workers_current. Compte des threads, pas des requêtes — en mode worker, un thread multiplexe de nombreuses Fibers de requête et ne compte qu'une fois. Les requêtes en attente d'admission ou assises dans la file ne sont pas comptées ; celles-là apparaissent dans oxphp_pending_requests |
oxphp_workers_spawned_total |
counter | Total des workers créés depuis le démarrage (inclut les workers initiaux) |
oxphp_workers_retired_total |
counter | Total des workers retirés en raison d'un délai d'inactivité (mode dynamique uniquement) |
Métriques du superviseur de workers
Observabilité par worker émise par le superviseur de workers. Chaque série porte un label worker_id (index de slot). Ces métriques apparaissent une fois que le superviseur suit l'état de chaque worker.
| Métrique | Type | Description |
|---|---|---|
oxphp_worker_request_age_seconds |
gauge | Âge de la requête en cours de traitement sur chaque worker, en secondes. Label : worker_id |
oxphp_worker_long_running_total |
counter | Analyses du superviseur ayant observé une requête plus ancienne que le seuil de blocage. Label : worker_id |
oxphp_worker_stuck_total |
counter | Compteur de classification de blocage par worker. Labels : worker_id, kind (io, c_call, cpu) |
Histogramme d'attente en file
| Métrique | Type | Description |
|---|---|---|
oxphp_queue_wait_us |
histogram | Temps qu'une requête attend dans la file avant qu'un worker ne la prenne en charge, en microsecondes |
Limites des buckets (microsecondes) : 50, 100, 250, 500, 1000, 2500, 5000, 10000, 50000, 100000, 250000, 500000, 1000000, +Inf.
Ceci mesure le temps passé à attendre — pour l'admission puis dans la file — en soustrayant le temps d'exécution propre au script, si bien qu'il répond à « combien de temps avant qu'un worker ne prenne cette requête » plutôt qu'à « combien de temps la requête a-t-elle pris ». Les requêtes refusées avec un 529 n'ont jamais été mises en file et ne sont pas enregistrées ici ; comptez-les avec oxphp_admission_refused_total.
Des temps d'attente en file élevés indiquent que tous les workers sont occupés et que vous devriez augmenter PHP_WORKERS. La plage atteint une seconde, en accord avec le QUEUE_WAIT_TIMEOUT_MS par défaut, si bien qu'une requête qui a dépensé l'essentiel de son budget d'attente avant de s'exécuter est quantifiée plutôt que reléguée dans +Inf. Rien de ce qui est servi n'attend plus longtemps que le budget — au-delà, la requête est refusée — donc relever QUEUE_WAIT_TIMEOUT_MS est le seul réglage qui renvoie des attentes dans +Inf.
Métriques de limitation de débit
| Métrique | Type | Description |
|---|---|---|
oxphp_rate_limited_total |
counter | Requêtes rejetées par le limiteur de débit (429 renvoyé) |
oxphp_php_deny_total |
counter | Requêtes bloquées par PHP_DENY_PATHS (exécution .php refusée). Voir Liste de refus d'exécution PHP |
Métriques du cache de fichiers statiques
| Métrique | Type | Description |
|---|---|---|
oxphp_static_cache_hits_total |
counter | Requêtes de fichiers statiques servies depuis le cache en mémoire |
oxphp_static_cache_misses_total |
counter | Requêtes de fichiers statiques ayant nécessité une lecture disque |
Métriques de compression
| Métrique | Type | Description |
|---|---|---|
oxphp_compressed_responses_total |
counter | Réponses compressées avec Brotli |
oxphp_compression_bytes_saved_total |
counter | Total des octets économisés par la compression (taille originale moins taille compressée) |
Métriques du mode worker
Ces métriques ne sont émises que lorsque le mode worker est actif (WORKER_MODE_ENABLED=true).
Compteurs globaux
| Métrique | Type | Description |
|---|---|---|
oxphp_worker_mode_enabled |
gauge | Toujours 1 lorsque le mode worker est actif |
oxphp_worker_requests_handled_total |
counter | Total des requêtes traitées par les workers persistants |
oxphp_worker_recycles_total |
counter | Total des recyclages de workers (un worker s'est arrêté et a été recréé) |
oxphp_worker_recycles_by_reason_total |
counter | Recyclages par raison. Label : reason (scheduled, max_memory, error) |
oxphp_worker_soft_resets_total |
counter | Total des réinitialisations souples effectuées entre les requêtes |
Jauges par worker
| Métrique | Type | Description |
|---|---|---|
oxphp_worker_memory_bytes |
gauge | Utilisation actuelle du tas PHP par worker. Label : worker (index de slot, p. ex. "0", "1") |
oxphp_worker_uptime_seconds |
gauge | Secondes écoulées depuis la création de chaque worker. Label : worker |
oxphp_worker_requests_count |
gauge | Requêtes traitées par chaque instance de worker. Label : worker |
Histogramme de durée de requête des workers
| Métrique | Type | Description |
|---|---|---|
oxphp_worker_request_duration_us |
histogram | Temps d'exécution du gestionnaire PHP par requête en microsecondes (mode worker uniquement) |
Limites des buckets (microsecondes) : 100, 250, 500, 1000, 2500, 5000, 10000, 25000, 50000, +Inf.
Cet histogramme mesure le temps passé à l'intérieur du callback du gestionnaire PHP, hors temps d'attente en file. Utilisez-le pour identifier les gestionnaires lents et suivre la latence de queue en mode worker.
Métriques du pool asynchrone
Ces métriques nécessitent que ASYNC_WORKERS soit défini à une valeur non nulle, et chacune possède sa propre condition d'émission : les compteurs n'apparaissent qu'après qu'au moins une tâche a été distribuée ou rejetée, les jauges _in_flight / _in_flight_limit apparaissent une fois que le pool a câblé son compteur de tâches en cours, et oxphp_async_output_discarded_bytes_total n'apparaît qu'après que de la sortie a été rejetée.
| Métrique | Type | Description |
|---|---|---|
oxphp_async_tasks_dispatched_total |
counter | Total des tâches asynchrones distribuées au pool d'arrière-plan |
oxphp_async_tasks_completed_total |
counter | Tâches asynchrones terminées avec succès |
oxphp_async_tasks_failed_total |
counter | Tâches asynchrones ayant levé une exception |
oxphp_async_tasks_cancelled_total |
counter | Tâches asynchrones annulées |
oxphp_async_tasks_rejected_total |
counter | Tâches asynchrones rejetées à la distribution — parce que la file du pool était pleine ou que le plafond de tâches en cours (ASYNC_MAX_FIBERS × ASYNC_WORKERS) était atteint |
oxphp_async_tasks_stranded_total |
counter | Workers laissés en exécution au-delà d'un délai d'expiration await_race / await_any. Chaque tâche abandonnée peut prolonger RSHUTDOWN jusqu'à 5 secondes. |
oxphp_async_tasks_in_flight |
gauge | Tâches asynchrones actuellement en file ou en cours d'exécution (émise une fois que le pool câble son compteur de tâches en cours) |
oxphp_async_tasks_in_flight_limit |
gauge | Nombre maximal de tâches asynchrones concurrentes (ASYNC_MAX_FIBERS × ASYNC_WORKERS) |
oxphp_async_output_discarded_bytes_total |
counter | Octets de sortie de tâche asynchrone rejetés à l'inactivité du worker (un echo dans une tâche asynchrone n'a aucun client pour le recevoir) |
Conseils pour tableau de bord Grafana
Les requêtes PromQL suivantes sont utiles pour construire des tableaux de bord :
Taux de requêtes (requêtes par seconde) :
rate(oxphp_requests_total[5m])Temps de réponse moyen (millisecondes) :
rate(oxphp_request_duration_us_sum[5m])
/ rate(oxphp_requests_total[5m]) / 1000Durée de requête p99 (millisecondes) :
histogram_quantile(0.99, rate(oxphp_request_duration_us_bucket[5m])) / 1000Taux d'erreur (réponses 5xx en pourcentage) :
rate(oxphp_responses_by_status_total{status="5xx"}[5m])
/ rate(oxphp_requests_total[5m]) * 100Utilisation du pool de workers :
oxphp_busy_workers / oxphp_workers_currentC'est une vraie fraction entre 0 et 1. Des valeurs soutenues à 1 signifient que chaque worker est occupé et que les arrivées supplémentaires font la queue. Associez-la à rate(oxphp_admission_refused_total{reason=~"queue_full|wait_timeout|waiting_full|waiting_bytes"}[5m]) pour voir si cet arriéré se transforme en refus, et à oxphp_pending_requests pour en mesurer la profondeur.
Saturation de la file (taux d'abandon par seconde) :
rate(oxphp_dropped_requests_total[5m])Attente en file p99 (microsecondes) :
histogram_quantile(0.99, rate(oxphp_queue_wait_us_bucket[5m]))Taux de succès du cache de fichiers statiques :
rate(oxphp_static_cache_hits_total[5m])
/ (rate(oxphp_static_cache_hits_total[5m]) + rate(oxphp_static_cache_misses_total[5m]))Octets économisés par la compression par seconde :
rate(oxphp_compression_bytes_saved_total[5m])Latence p99 en mode worker (microsecondes) :
histogram_quantile(0.99, rate(oxphp_worker_request_duration_us_bucket[5m]))Taux de recyclage des workers (par minute) :
rate(oxphp_worker_recycles_total[5m]) * 60Utilisation mémoire moyenne des workers :
avg(oxphp_worker_memory_bytes)Configuration de scraping Prometheus
Ajoutez un job de scraping à votre prometheus.yml :
scrape_configs:
- job_name: "oxphp"
scrape_interval: 15s
static_configs:
- targets: ["oxphp:9090"]Pour la découverte de services 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"Voir aussi
- Contrôles de santé — les endpoints
/healthet/configsur le serveur interne - Référence de configuration — toutes les variables d'environnement, y compris
INTERNAL_ADDR - Arrêt gracieux — comment le drainage des connexions affecte
oxphp_active_connections - Mode worker — les workers persistants et les métriques qu'ils émettent