infra / monitoring-observabilite
PromQL de base
Explication
Ce que vous allez apprendre
- Filtrer des séries temporelles par label, y compris avec des expressions régulières
- Comprendre la différence entre un vecteur instantané et un vecteur de plage (
[5m]) - Utiliser
rate()pour transformer un compteur cumulatif en débit exploitable - Agréger des métriques par dimension avec
sum(...) by (...) - Calculer un taux d'erreur et un percentile de latence, les deux requêtes les plus utilisées en dashboard
Dans quel contexte ?
mon-api expose désormais ses métriques (leçon précédente), mais un chiffre brut comme http_requests_total{status="500"} = 1204 ne dit rien d'utile en soi : 1204 erreurs en un an n'a rien à voir avec 1204 erreurs en 5 minutes. Il faut un langage pour transformer ces compteurs bruts en informations exploitables — c'est exactement le rôle de PromQL.
D'abord, la forme la plus simple d'une requête
Taper juste http_requests_total renvoie la valeur actuelle de chaque série correspondant à ce nom de métrique. Pour restreindre le résultat, on ajoute des filtres entre accolades sur les labels, comme http_requests_total{status="500"} pour ne garder que les erreurs serveur.
Ces filtres peuvent aussi utiliser des expressions régulières, avec =~ pour "correspond à" et !~ pour "ne correspond pas à" — très utile pour cibler toute une famille de status codes d'un coup (status=~"5..").
Une fois le filtrage acquis, il reste un problème : un compteur brut ne dit rien sur sa vitesse
http_requests_total continue de grimper indéfiniment tant que l'application tourne. Savoir qu'il vaut "8421" à un instant donné ne renseigne ni sur le trafic actuel ni sur une tendance. Il faut regarder son évolution sur une fenêtre de temps.
C'est là qu'intervient le "range vector" : http_requests_total[5m] récupère toutes les valeurs des 5 dernières minutes plutôt qu'une seule valeur instantanée. Cette syntaxe entre crochets est indispensable pour toute fonction qui calcule un débit.
| Fonction | Rôle | Exemple |
|---|---|---|
rate() | Débit moyen par seconde sur la fenêtre | rate(http_requests_total[5m]) |
increase() | Croissance totale sur la fenêtre (pas par seconde) | increase(http_requests_total[1h]) |
sum() by (...) | Agrégation groupée par label | sum(rate(...)) by (status) |
histogram_quantile() | Percentile calculé depuis un Histogram | histogram_quantile(0.95, ...) |
Prérequis
Il faut avoir des métriques réellement exposées par une application pour suivre cette leçon efficacement (voir la leçon précédente sur l'instrumentation) ; les exemples utilisent directement http_requests_total et http_request_duration_seconds_bucket.
rate() est la fonction la plus utilisée de tout PromQL — voici pourquoi
rate(http_requests_total[5m]) convertit ce compteur toujours croissant en "requêtes par seconde" sur les 5 dernières minutes. Elle gère aussi intelligemment les redémarrages de l'application (quand le compteur retombe brutalement à zéro), ce qu'un simple calcul de différence manuel ne ferait pas correctement.
Piège fréquent
N'applique jamais rate() directement sur un Gauge : cette fonction n'a de sens que sur un Counter, qui ne fait qu'augmenter. Sur un Gauge (qui monte et descend), le résultat de rate() serait mathématiquement absurde et trompeur.
Maintenant que tu sais mesurer un débit, il faut apprendre à le regrouper
Sans agrégation, PromQL renvoie une série PAR combinaison de labels, ce qui devient vite illisible dès qu'une métrique a plusieurs dimensions. sum(rate(http_requests_total[5m])) by (status) résout ça : il additionne toutes les séries qui partagent le même status, ne gardant qu'une ligne par valeur de status.
Bonne pratique
Le calcul de taux d'erreur (5xx / total * 100) et le calcul de P95 avec histogram_quantile() reviennent dans quasiment tous les dashboards de production. Mémorise ces deux formules par coeur : elles servent de base à l'alerting comme au reporting.
Le piège à éviter en fin de leçon
Une erreur fréquente est d'oublier que histogram_quantile() s'applique sur le résultat d'un sum(...) by (le) et non directement sur le bucket brut : le label le (less than or equal), créé automatiquement par chaque Histogram, doit être préservé dans le regroupement, sinon la fonction ne peut pas reconstruire la distribution.
Une fois ces bases solides, la leçon suivante va plus loin avec des fonctions PromQL plus avancées : jointures entre métriques, extrapolation et détection d'absence de données.
Commandes & code
PromQL de base
# Requête instantanée : valeur actuelle d'une série
http_requests_total
# Filtrer par label (égalité exacte)
http_requests_total{status="500"}
# Filtrer par plusieurs labels (ET implicite)
http_requests_total{status="500", method="POST"}
# Opérateurs de comparaison sur les labels
http_requests_total{status=~"5.."} # regex : tous les status 5xx
http_requests_total{status!~"2.."} # regex négative : tout SAUF les 2xx
http_requests_total{path!="/health"} # différent de# range vector : valeurs sur une FENÊTRE de temps (nécessaire pour rate/increase)
http_requests_total[5m] # toutes les valeurs des 5 dernières minutes
# rate() : taux de croissance par seconde, calculé sur la fenêtre — LA fonction la plus utilisée
rate(http_requests_total[5m])
# -> convertit un compteur brut en "requêtes par seconde", gère aussi les resets (redémarrage du process)
# increase() : croissance TOTALE sur la fenêtre (pas par seconde)
increase(http_requests_total[1h]) # nombre de requêtes reçues sur la dernière heure# Agrégations : sum, avg, max, min, count — avec "by" pour grouper, "without" pour exclure des labels
sum(rate(http_requests_total[5m])) # débit total, toutes dimensions confondues
sum(rate(http_requests_total[5m])) by (status) # débit par status code
sum(rate(http_requests_total[5m])) by (method, path) # débit par méthode ET par route
sum(rate(http_requests_total[5m])) without (instance) # tout sauf le label "instance"
avg(http_request_duration_seconds) by (path) # latence moyenne par route
max(node_memory_usage_bytes) by (instance) # pic mémoire par serveur# Combiner plusieurs métriques : taux d'erreur (%) — requête ULTRA classique en dashboard
sum(rate(http_requests_total{status=~"5.."}[5m]))
/
sum(rate(http_requests_total[5m]))
* 100
# Comparer dans le temps avec offset : "il y a 1 semaine" pour détecter une anomalie
rate(http_requests_total[5m]) - rate(http_requests_total[5m] offset 1w)# Histogram : calculer des percentiles avec histogram_quantile()
histogram_quantile(0.95, sum(rate(http_request_duration_seconds_bucket[5m])) by (le))
# -> latence au 95e percentile (P95) : 95% des requêtes sont plus rapides que cette valeur
# "le" (less than or equal) est le label automatique créé par les buckets d'un Histogram| Fonction | Usage |
|---|---|
rate() | débit par seconde sur un counter (le plus utilisé) |
increase() | croissance totale sur la fenêtre |
sum() by(...) | agrégation groupée par label |
histogram_quantile() | percentiles depuis un Histogram |
offset | comparer avec une période passée |
Résumé
rate()sur un[5m]est la requête la plus courante : convertit un compteur cumulatif en débit par seconde exploitable.sum(...) by (label)groupe l'agrégation par dimension ;withoutfait l'inverse (exclut des labels du groupement).- Le calcul du taux d'erreur (
5xx / total * 100) et du P95 (histogram_quantile) sont les deux requêtes à maîtriser en priorité.
Exercices pratiques
Mission : le dashboard qui ment
Objectif : Corriger des requêtes PromQL mal construites qui donnent des chiffres trompeurs sur le trafic, le taux d'erreur et la latence.
Contexte
Un dashboard existant affiche http_requests_total brut sur un panel nommé "Trafic actuel", un taux d'erreur calculé avec rate() appliqué à un Gauge de connexions actives, et un P95 obtenu en appliquant histogram_quantile() directement sur les buckets bruts sans sum() by (le). Ton travail : identifier et corriger chaque requête cassée.