Lab 4 — Dashboard unifié logs / métriques / traces
Vous disposez maintenant des trois signaux : traces (Labs 2), métriques système et produit (Lab 3), logs (collectés d’office par la démo). Dans ce lab, vous les rassemblez dans un seul dashboard Grafana : la « vue service » que consulterait un astreinte.
Vous en construisez deux panels — un de métriques, un de traces — puis vous importez le dashboard de référence, qui apporte les autres. Vous terminez par une règle d’alerte sur la latence.
Prérequis
- Labs 1 à 3 terminés.
- D’abord les variables de la formation chargées dans votre shell :
. ./scripts/env.sh— elles donnent$PF_HOSTet$UI_PORT, l’adresse et le port de vos UIs. - Ensuite les accès :
./scripts/open-ui.sh. Le script affiche l’URL de Grafana,http://$PF_HOST:$UI_PORT/grafana/— soithttp://localhost:8080/grafana/sur un poste individuel, maishttp://localhost3:8080/grafana/pour student3 sur le serveur partagé.
Étapes
- Explorer les datasources déjà câblées :
Dans Grafana : ⚙️ Connections → Data sources. Trois sources correspondent à nos trois signaux — identifiez-les et notez leur type.
💡 Où lire l’UID d’une datasource. En une phrase : l’UID est l’adresse d’une datasource à l’intérieur de Grafana. C’est par lui qu’un panel dit « mes données viennent de Prometheus ».
Dans l’interface, ouvrez la datasource : l’UID est dans l’URL, en dernier segment —
.../grafana/connections/datasources/edit/webstore-metrics.En ligne de commande (la démo autorise l’accès anonyme avec le rôle Admin : aucun jeton à créer) :
Ces UID servent aussi à relier les datasources entre elles — c’est ce qui permettra, au Lab 4.1, de passer d’un point de métrique à la trace correspondante.
- Créer un dashboard vide (Dashboards → New → New dashboard), puis ajouter la variable
service_name:
Settings → Variables → New variable :
- Type
Query, datasource Prometheus - Query :
label_values(traces_span_metrics_calls_total, service_name)
💡 Ce que fait cette ligne. Une variable ajoute un menu déroulant en haut du dashboard. Partout où un panel écrira
$service_name, Grafana remplacera par la valeur choisie avant d’interroger Prometheus : sélectionnezcheckout, etservice_name=~"$service_name"part enservice_name=~"checkout". Un seul dashboard suffit donc pour les quinze services de la boutique, au lieu d’un par service.
label_values(...)n’est pas du PromQL : c’est une fonction de Grafana, réservée aux variables de type Query. Elle se lit « donne-moi toutes les valeurs du labelservice_nameprésentes sur la métriquetraces_span_metrics_calls_total». Le menu se remplit donc tout seul — rien n’est écrit en dur — et suit les services qui apparaissent ou disparaissent.Reste le choix de la métrique.
traces_span_metrics_calls_totalest produite par le connector spanmetrics du collecteur (vu au Lab 3), qui compte les spans qu’il voit passer : elle est donc dérivée des traces. Le menu liste ainsi exactement les services qui tracent — y comprisreview-service, qui hérite au passage de métriques de débit et de latence sans avoir été instrumenté pour les métriques !
- Panel 1 — métriques (Prometheus) : un Time series « Débit de requêtes » :
💡 Cette requête, mot à mot. Elle se lit de l’intérieur vers l’extérieur, et chacun des trois morceaux répond à une question différente.
traces_span_metrics_calls_total{service_name=~"$service_name"}— quoi ? Un compteur produit par spanmetrics : le nombre de spans vus depuis le démarrage du collecteur. Le suffixe_totalest la convention Prometheus pour un compteur, une valeur qui ne fait que monter. Entre accolades, le filtre : seulement le service choisi dans le menu.rate(...[2m])— à quelle vitesse ? Un compteur brut ne se lit pas : « 48 219 spans depuis le démarrage » n’apprend rien.rateen prend la pente sur les 2 dernières minutes et rend des spans par seconde. C’est cela qu’on veut voir monter et descendre.sum(...)— combien en tout ? spanmetrics ne tient pas un compteur par service, mais un par opération (span_name), sens d’appel (span_kind) et statut. Sanssum, le panel afficherait des dizaines de courbes ;sumles écrase en une seule, le débit total du service.L’ordre compte : toujours
rated’abord,sumensuite.ratesait reconnaître qu’un compteur est reparti de zéro — un pod du collecteur qui redémarre — et corriger ; mais il ne le peut que série par série. Additionnez avant, et la baisse se lit comme une remise à zéro du total : le panel affiche alors un pic de trafic au moment précis où un pod est mort. La démonstration chiffrée est dans le Lab 4 bonus.
- Panel 2 — traces (Jaeger) : datasource Jaeger, query type Search, service
$service_name, limit 20.
⚠️ Le panel restera vide tant que vous n’aurez pas coché Table view, l’interrupteur en haut de l’éditeur de panel. La visualisation par défaut est un graphe temporel : elle ne sait pas représenter une liste de traces, et n’affiche donc rien du tout — sans message d’erreur, ce qui laisse croire que la requête est en cause. Elle ne l’est pas : la requête ci-dessus est correcte. (Vous pouvez aussi choisir la visualisation Table dans le sélecteur en haut à droite ; Table view est simplement plus rapide.)
💡 Panels vides sur
review-service? C’est normal, et instructif : les services de la boutique reçoivent du trafic en permanence — le load generator s’en charge — mais le vôtre n’en reçoit que si vous lui en envoyez. Ses derniers logs peuvent dater de votre session précédente. Réveillez-le :(ou postez quelques avis depuis sa page web,
http://$PF_HOST:$APP_PORT/). Une vingtaine de secondes plus tard, les logsListing all reviewsremplissent le panel — et les panels Prometheus se garnissent de la même façon, sans requêtes il n’y a ni débit ni latence à tracer.Si le panel reste vide malgré le trafic, vérifiez qu’une instrumentation tourne : c’est elle qui transforme les logs de l’application en LogRecords envoyés au collecteur. Deux le font, et toutes deux capturent les logs — l’agent Java du Lab 2 (partie 1) comme le Spring Boot Starter (partie 2, celui que vous avez déployé en dernier).
Ni l’un ni l’autre — une image
default-…sansJAVA_TOOL_OPTIONS— et l’application n’émet rien du tout : ni logs, ni traces, ni métriques. C’est l’état du tout début du Lab 2, celui où Jaeger restait désespérément vide.
- Lire le panel « Latence p95 » du dashboard importé, et basculez la variable
service_nameentrefrontend,checkoutetreview-service: les quatre panels suivent.
Il se lit en une phrase : sur les deux dernières minutes, 95 % des spans de ce service ont été plus rapides que la valeur affichée.
À quoi sert-il ? À répondre « ça va, ou pas ? » — pas à expliquer pourquoi. Une métrique coûte trois fois rien et se garde des mois : elle dit qu’il y a un problème et depuis quand. Une trace, elle, dit laquelle des requêtes a souffert, mais elle est volumineuse et ne vit que quelques jours. D’où le p95 en vitrine et les traces juste derrière : le panel repère l’incident, le panel Traces récentes — et surtout les exemplars du Lab 4.1 — mènent à la requête fautive.
Pourquoi un percentile plutôt qu’une moyenne ? Parce qu’une moyenne noie les cas lents : dix requêtes à 10 ms et une à 2 s font une moyenne de 190 ms, qui ne décrit aucune des onze. Le p95 dit ce que vivent les 5 % les moins bien servis.
💡 Le détail de cette requête — ce qu’est un seau
le, pourquoi un percentile ne s’additionne pas, et ce que ce p95 ne dit pas — est dans le Lab 4 bonus.
- Installer la règle d’alerte. Le panel trace le p95 avec son seuil à 20 ms en rouge. Installez la règle qui surveille ce seuil : elle doit se déclencher quand le p95 du
review-servicedépasse 20 ms pendant 1 minute.
💡 Pourquoi deux commandes, et pas une ligne de plus dans le dashboard ? Parce qu’une règle d’alerte ne vit pas dans le dashboard. Jusqu’à Grafana 10 elle était rangée dans le JSON du panel ; l’alerting unifié l’en a sortie (l’ancien système a disparu en Grafana 11, et la démo tourne en 13). Une règle est désormais un objet à part, avec son API, et Grafana exige de la ranger dans un dossier et dans un groupe d’évaluation — ici le groupe
formation-otel, évalué toutes les 60 secondes. Elle reste toutefois rattachée au panel : le JSON contient l’uiddu dashboard et l’id du panel, c’est ce qui permet de passer de l’un à l’autre d’un clic.Le
X-Disable-Provenance: truemérite un mot : sans lui, Grafana marque la règle « provisionnée » et l’interface interdit de la modifier. Avec lui, vous pourrez ouvrir la règle et changer le seuil à la souris.Notez enfin le service, écrit en dur dans la requête :
service_name="review-service". Une règle d’alerte n’a pas de menu déroulant — la variable$service_namedu dashboard n’existe pas pour elle. Si vous créez une règle depuis un panel (Panel → More → New alert rule), Grafana y fige la valeur affichée au moment du clic, sans le dire.
- La faire sonner. Votre
review-servicen’a de trafic que celui que vous lui envoyez, et il est rapide : au repos, son p95 tourne autour de 4 ms. D’où le seuil à 20 ms — cinq fois le repos. Un seuil ne se choisit pas dans l’absolu, il se calibre sur le service qu’il surveille.
Pour le faire monter, ce n’est pas le nombre de requêtes qui compte, c’est le nombre de requêtes en même temps : cent clients en parallèle pendant trois minutes.
⚠️ Ce nombre dépend de la machine, et c’est instructif. Mesuré sur le serveur de formation (16 vCPU) : 30 clients donnent 2 260 req/s pour un p95 de 4,3 ms — l’alerte ne sonne jamais. Il faut 100 clients pour atteindre 2 100 req/s à 26,8 ms et franchir le seuil. Sur un portable, trente suffisent largement.
Si l’alerte reste obstinément
Normal, ne cherchez pas ailleurs : regardez d’abord où en est le p95, dans le panel ou dans Prometheus.S’il stagne sous 20 ms, doublez le nombre de clients. C’est exactement la leçon de l’étape : un seuil se calibre sur le service et sur la machine qui l’héberge, il ne se recopie pas d’un environnement à l’autre.
💡 Gardez la fenêtre
[2m]. Avec[1m], la requête renvoie souvent vide : le collecteur exporte toutes les 60 s, la fenêtre ne contient alors qu’un seul point, etrate()en exige deux. Pendant que ça tourne, remettez la variableservice_namesurreview-serviceet regardez le panel « Latence p95 » : la courbe décolle et franchit la ligne rouge — mesuré sur le serveur de formation, 26,8 ms contre un seuil de 20. Puis la page Alerting → Alert rules, où la règle change d’état :
Normal— le p95 est sous le seuil ;Pending— il vient de passer au-dessus, mais la règle attend que le dépassement dure (sonfor, 1 minute) ;Firing— le dépassement a duré : l’alerte est déclarée.
Chronologie relevée en salle : Pending au bout d’une trentaine de secondes — la première évaluation qui voit le dépassement —, puis Firing à 1 min 40, à l’évaluation suivante, une fois le for écoulé. Le groupe s’évalue toutes les 60 secondes : il faut donc deux évaluations au-dessus du seuil.
Ces trois éléments — la condition (la ligne rouge), la durée (for), les états — sont tout ce qui fait une alerte. Le for est ce qui sépare un pic isolé d’un incident : sans lui, la moindre requête lente réveillerait quelqu’un.
💡 Deux choses qui surprennent. D’abord, rien n’arrive dans aucune boîte : la démo ne configure aucun point de contact, l’alerte se lit donc dans l’interface et nulle part ailleurs. Ensuite, quand vous arrêtez la charge, le retour à
Normalprend encore deux bonnes minutes : la requête moyenne les latences sur une fenêtre de deux minutes (rate(...[2m])), et cette fenêtre doit d’abord se vider des requêtes lentes.
💡 En production, cette alerte ne vivrait probablement pas dans Grafana. On l’écrirait côté Prometheus, en YAML versionné dans Git :
Vous y retrouvez exactement les trois éléments observés :
exprest la condition,forla durée, et les étatsPending→Firingsont les mêmes. Seul l’endroit change — et cela change trois choses : la règle est revue en PR comme du code, elle est évaluée par Prometheus même si Grafana est éteint, et Alertmanager prend en charge ce que Grafana ne fait qu’en partie : déduplication, groupement, silences pendant une maintenance, routage vers Slack ou PagerDuty.L’alerting Grafana garde un avantage que Prometheus ne peut pas avoir : il est multi-datasources. Une règle Grafana peut croiser une métrique Prometheus et des logs OpenSearch dans la même condition ; une règle Prometheus ne voit que du PromQL.
Pourquoi ce lab ne la déploie pas de ce côté-là : la démo désactive
alertmanager(aucune notification à recevoir) etconfigmapReload(Prometheus ne relit pas sa configuration à chaud). Il faudrait unhelm upgradeet un redémarrage de Prometheus pour voir passer trois lignes de YAML.
- Exporter votre dashboard en JSON (Share → Export → Save to file) : c’est le livrable, à committer dans votre dépôt — même s’il ne contient que la variable et vos deux panels.
Pour aller plus loin
- Lab 4.1 — Exemplars : du point de métrique à la trace — le chaînon qui manque entre le p95 et Jaeger, sur un dashboard livré par la démo. Rien à construire, tout à lire.
- Lab 4 bonus — Lire un histogramme : p95 et heatmap — le PromQL des seaux, ce que le p95 cache, et pourquoi une heatmap en dit parfois davantage.
Livrable
Votre dashboard « vue service » exporté en JSON, avec sa variable service_name et au moins un panel qu’elle pilote — et la règle d’alerte vue passer en Firing. Le dashboard de référence importé au bloc « Solution » montre la cible complète — les trois signaux d’un même service côte à côte.