infra / monitoring-observabilite
PromQL avancé
Explication
Ce que vous allez apprendre
- Joindre deux métriques différentes avec
group_left/group_rightpour enrichir un résultat - Anticiper une saturation future avec
predict_linear() - Identifier rapidement les séries extrêmes avec
topk()etbottomk() - Détecter la disparition totale d'une métrique avec
absent() - Pré-calculer des requêtes coûteuses avec des recording rules
Dans quel contexte ?
Une équipe SRE surveille une trentaine de services, mais les alertes actuelles ne remontent que des taux d'erreur bruts sans savoir à quelle équipe ni quel environnement ils appartiennent. Le PromQL de base (leçon précédente) filtre et agrège une seule métrique à la fois ; il faut maintenant apprendre à combiner plusieurs métriques et à anticiper des problèmes avant qu'ils n'arrivent.
D'abord, un cas très courant : comparer deux métriques entre elles
Les opérateurs binaires (/, >, -) fonctionnent aussi entre deux résultats PromQL complets, à condition que leurs labels correspondent. C'est ainsi qu'on calcule un taux d'erreur par service : diviser le débit d'erreurs par le débit total, puis filtrer avec > 0.05 pour ne garder que les services vraiment problématiques.
Ce filtrage par comparaison transforme une métrique numérique en une sorte de "requête booléenne" : le résultat ne contient plus que les séries qui satisfont la condition, les autres disparaissent silencieusement du résultat.
Une fois ça acquis, il reste un problème : comment enrichir une métrique technique avec du contexte métier ?
Une métrique technique comme http_requests_total ne connaît généralement pas l'équipe propriétaire ou l'environnement business du service. Ces informations vivent parfois dans une métrique séparée, purement informative (valeur toujours égale à 1), qui ne sert qu'à porter des labels.
C'est le rôle de group_left/group_right : joindre deux métriques de cardinalités différentes, un peu comme une jointure SQL "many-to-one". group_left signifie que le côté gauche de l'opération peut avoir plusieurs séries pour une seule série du côté droit.
| Fonction avancée | Rôle | Cas d'usage typique |
|---|---|---|
group_left/group_right | Jointure entre métriques de cardinalités différentes | Enrichir avec des labels métier (équipe, environnement) |
predict_linear() | Extrapolation linéaire dans le futur | Anticiper une saturation disque/mémoire |
topk()/bottomk() | N séries les plus/moins élevées | "Qui consomme le plus", "quelle instance est la moins fiable" |
absent() | Détecte l'absence totale d'une série | Alerter si un exporter a disparu du scraping |
Prérequis
Cette leçon suppose une bonne maîtrise du PromQL de base : rate(), sum(...) by (...) et les filtres par label doivent déjà être des réflexes avant d'aborder les jointures.
Maintenant, une capacité que peu de systèmes de monitoring offrent nativement : prédire l'avenir
predict_linear() prend les valeurs des dernières heures d'une Gauge et extrapole linéairement leur évolution dans le futur. Appliqué à l'espace disque libre, il permet d'alerter "ce disque sera plein dans 4 heures" plutôt que d'attendre qu'il le soit réellement.
Astuce
Combine predict_linear() avec un for: généreux (10 à 15 minutes) dans tes règles d'alerte : une extrapolation basée sur un pic ponctuel et transitoire donnerait sinon de fausses alertes de saturation imminente.
Il reste un dernier cas particulier, contre-intuitif au premier abord : l'absence de données
Toutes les fonctions vues jusqu'ici travaillent sur des séries qui EXISTENT. Mais que se passe-t-il si un exporter tombe complètement en panne et arrête d'envoyer la moindre métrique ? Aucune des requêtes précédentes ne peut détecter ce silence, puisqu'il n'y a tout simplement plus rien à interroger.
Piège fréquent
Une alerte du type up{job="mon_api"} == 0 ne se déclenche QUE si la série up existe encore mais vaut 0. Si le job disparaît totalement de la configuration de scraping (erreur de déploiement, service supprimé par erreur), cette alerte reste silencieuse. absent(up{job="mon_api"}) couvre ce cas en détectant l'absence complète de la série elle-même.
Pour finir, un mot sur la performance : les recording rules
Une requête PromQL complexe, réutilisée dans dix dashboards différents et recalculée à chaque rafraîchissement, finit par coûter cher en ressources. Les recording rules pré-calculent ce résultat en arrière-plan, à intervalle régulier, et le stockent sous un nouveau nom de métrique bien plus rapide à interroger ensuite.
Maintenant que la manipulation de métriques n'a plus de secret, la suite logique est de leur donner une forme visuelle exploitable : direction Grafana pour construire de vrais dashboards.
Commandes & code
PromQL avancé
# Opérateurs binaires entre séries : jointure automatique sur les labels communs
(
sum(rate(http_requests_total{status=~"5.."}[5m])) by (service)
/
sum(rate(http_requests_total[5m])) by (service)
) > 0.05
# -> ne garde que les services dont le taux d'erreur dépasse 5% (filtre booléen sur le résultat)# group_left / group_right : jointure many-to-one entre métriques aux cardinalités différentes
# Exemple : enrichir une métrique technique avec un label métier venant d'une autre métrique
sum(rate(http_requests_total[5m])) by (instance)
* on(instance) group_left(team, env)
service_info{}
# service_info est une métrique "statique" (valeur=1) qui sert juste à porter des labels supplémentaires# predict_linear() : extrapolation linéaire — utile pour anticiper une saturation
predict_linear(node_filesystem_free_bytes[6h], 4 * 3600) < 0
# -> prédit si l'espace disque libre atteindra 0 dans les 4 prochaines heures, sur la base des 6 dernières heures
# deriv() : dérivée (pente) d'une gauge dans le temps
deriv(process_resident_memory_bytes[10m]) # mémoire en train de fuir si constamment positif et croissant# topk / bottomk : les N séries les plus/moins élevées — pratique pour "qui consomme le plus"
topk(5, sum(rate(http_requests_total[5m])) by (path)) # top 5 routes les plus sollicitées
bottomk(3, avg_over_time(up[1h]) by (instance)) # 3 instances avec la plus mauvaise dispo
# avg_over_time, max_over_time, min_over_time : agrégation sur une fenêtre glissante (pas juste instantané)
avg_over_time(http_request_duration_seconds[1h])# absent() : détecte l'ABSENCE d'une métrique — essentiel pour alerter "un exporter a disparu"
absent(up{job="mon_api"})
# renvoie 1 si AUCUNE série ne matche (ex: le job a totalement disparu du scraping)
# changes() : nombre de changements de valeur sur la fenêtre (détecte des redémarrages via un counter qui reset)
changes(process_start_time_seconds[1h]) > 0# Recording rules : pré-calculer des requêtes coûteuses/fréquentes, exécutées en arrière-plan par Prometheus
# rules/recording_rules.yml
groups:
- name: api_recording_rules
interval: 30s
rules:
- record: job:http_requests:rate5m # convention de nommage : niveau:métrique:fonction
expr: sum(rate(http_requests_total[5m])) by (job)
- record: job:http_error_rate:ratio5m
expr: |
sum(rate(http_requests_total{status=~"5.."}[5m])) by (job)
/
sum(rate(http_requests_total[5m])) by (job)# prometheus.yml : brancher les fichiers de règles
rule_files:
- "rules/recording_rules.yml"
- "rules/alerting_rules.yml" # voir leçon AlertingRésumé
group_left/group_rightjoignent des métriques de cardinalités différentes pour enrichir un résultat avec des labels métier.predict_linear()anticipe une saturation (disque, mémoire) avant qu'elle ne se produise réellement — clé pour l'alerting proactif.topk/bottomkidentifient rapidement les séries extrêmes ;absent()détecte la disparition totale d'une métrique/exporter.- Les recording rules pré-calculent les requêtes lourdes et répétées (dashboards, alertes) : gain de performance en production à grande échelle.
Exercices pratiques
Mission : disque plein dans combien de temps ?
Objectif : Utiliser les fonctions PromQL avancées (predict_linear, absent, topk) pour anticiper une panne et détecter un exporter disparu.
Contexte
L'équipe SRE surveille 30 services. Un disque approche dangereusement de sa capacité, un exporter a disparu du scraping sans que personne ne s'en aperçoive, et personne ne sait quelle route consomme le plus de trafic. Tu dois écrire les requêtes qui répondent à ces trois problèmes distincts.