Votre cluster est couvert de métriques. node_exporter remonte le CPU, la RAM et le remplissage des disques, kube-state-metrics connaît l’état de chaque pod. Puis un responsable produit demande : « le paiement est-il plus lent que ce matin ? », et personne ne sait répondre. Toutes ces métriques décrivent les machines et l’orchestrateur ; aucune ne décrit ce que fait votre application. C’est exactement le trou que l’instrumentation comble : exposer, depuis le code, les quelques chiffres qui disent si le service rend le service.

Les quatre signaux, et par où commencer

La grille la plus utile reste celle des golden signals du livre SRE de Google : la latence (combien de temps une requête prend), le trafic (combien vous en recevez), les erreurs (combien échouent) et la saturation (à quel point vos ressources sont sollicitées). La saturation est déjà largement couverte par node_exporter et les métriques du cluster. Restent trois choses à instrumenter dans l’application elle-même, ce que la méthode RED résume bien pour un service qui répond à des requêtes : Rate, Errors, Duration.

Autrement dit, avant d’ajouter la moindre métrique métier, exposez combien de requêtes arrivent, combien tournent mal, et combien de temps elles durent. Tout le reste sert au diagnostic une fois qu’un de ces trois signaux vous a alerté.

Le bon type de métrique pour la bonne question

Prometheus a quatre types de métriques, et le choix n’est pas cosmétique. Un counter ne fait que monter et se lit avec rate() : c’est le type du trafic et des erreurs, un http_requests_total porteur d’un label status. Une gauge est une valeur instantanée qui monte et descend, pour ce qui se compte à un instant donné (connexions en cours, profondeur d’une file). Un histogram échantillonne une distribution dans des tranches prédéfinies, et c’est le bon outil pour la latence. Le summary ressemble à l’histogramme mais calcule ses quantiles autrement, avec une conséquence lourde qu’on verra plus bas.

Un handler instrumenté, et les requêtes qui vont avec

Concrètement, votre bibliothèque cliente expose au scrape un format texte de ce genre :

# TYPE http_requests_total counter
http_requests_total{service="checkout",status="200"} 128934
http_requests_total{service="checkout",status="500"} 271

# TYPE http_request_duration_seconds histogram
http_request_duration_seconds_bucket{service="checkout",le="0.1"} 24054
http_request_duration_seconds_bucket{service="checkout",le="0.3"} 33444
http_request_duration_seconds_bucket{service="checkout",le="1"}   34101
http_request_duration_seconds_bucket{service="checkout",le="+Inf"} 34115
http_request_duration_seconds_sum{service="checkout"}   5342.7
http_request_duration_seconds_count{service="checkout"} 34115

L’histogramme expose des compteurs cumulatifs par borne le (less than or equal), plus un _sum et un _count. À partir de là, deux requêtes couvrent l’essentiel :

# taux d'erreur par service
sum(rate(http_requests_total{status=~"5.."}[5m])) by (service)
  /
sum(rate(http_requests_total[5m])) by (service)

# latence p99 par service
histogram_quantile(
  0.99,
  sum by (service, le) (rate(http_request_duration_seconds_bucket[5m]))
)

Ce sont précisément les métriques que consomment les alertes Prometheus par symptôme : instrumenter d’abord, alerter ensuite. Une règle qui surveille le taux d’erreur ou la latence n’existe que parce que l’application a été instrumentée pour les exposer.

Histogramme ou summary : pourquoi le quantile se calcule côté serveur

Voici la distinction qui décide du type à choisir. Un summary calcule ses quantiles dans le client, par instance, et publie directement un quantile="0.99". Le problème : on ne peut ni additionner ni moyenner des quantiles. Le p99 de dix pods n’est pas la moyenne de leurs dix p99. Dès que votre service tourne en plusieurs réplicas, un summary vous donne dix chiffres impossibles à recombiner en une latence de service.

L’histogramme fait l’inverse : il expose des comptes bruts par tranche, et histogram_quantile() reconstitue le quantile côté serveur, après que vous avez agrégé les buckets avec sum by (le). Comme tout tourne en plusieurs exemplaires sur Kubernetes, l’histogramme est le choix par défaut. Son coût : il faut choisir les tranches à l’avance.

Les buckets, l’interpolation, et les pièges

histogram_quantile() interpole linéairement à l’intérieur de la tranche où tombe le quantile. La précision de votre p99 est donc la largeur du bucket qui l’entoure. Les tranches par défaut (de quelques millisecondes à dix secondes) encadrent rarement un objectif réel : placez les bornes là où vous prenez des décisions. Si votre cible est 300 ms, vous voulez des bornes vers 0.25, 0.3, 0.5. Et si le quantile tombe dans la tranche +Inf, le résultat n’est plus une valeur mais une borne inférieure, signe que vos buckets sont trop grossiers. Les histogrammes natifs, plus récents, suppriment ce choix de bornes au prix d’un statut encore expérimental.

Trois autres pièges reviennent. La cardinalité d’abord : un label par utilisateur, par URL brute ou par identifiant de requête multiplie les séries par le nombre de buckets et fait exploser le coût de stockage, un sujet que détaille l’entrée de glossaire sur la cardinalité des métriques. Gardez des labels bornés : le gabarit de route, pas le chemin brut ; la classe de statut, pas le message complet. Moyenner des quantiles ensuite, avg d’un p99, qui ne veut rien dire : on agrège les buckets, jamais les quantiles. Trop peu de tranches autour de l’objectif enfin, qui rend le p99 illisible au moment précis où il compte.

À retenir

Instrumentez trois choses depuis le code, trafic, erreurs et durée, et laissez la saturation à node_exporter. Un counter pour les taux, un histogramme pour la latence, avec ses bornes posées autour de la décision que vous prenez vraiment. Préférez l’histogramme au summary dès que le service tourne en plusieurs réplicas, et tenez la cardinalité des labels, parce qu’une application instrumentée qui coûte plus qu’elle n’observe est un incident comme un autre. Cette observabilité utile est le socle de mon offre fiabilité et observabilité ; d’autres sujets dans la catégorie observabilité.