← Tous les cours / Les 3 piliers de l'observabilité Cours
00 — VUE D'ENSEMBLE

Du monitoring à l'observabilité

Ton serveur est en feu. Tu regardes les dashboards, tout est vert. C'est le problème.

Pendant longtemps, "surveiller son infrastructure" voulait dire : définir des seuils, configurer des alertes, regarder des courbes de CPU. C'est le monitoring. Ça répond à une question : est-ce que ça marche ?

Le problème, c'est que cette question est trop simple pour les systèmes modernes. Une application distribuée peut présenter des latences anormales sans qu'aucun seuil ne soit dépassé. Un service peut fonctionner parfaitement pendant que ses clients reçoivent des erreurs. Tu peux avoir 99 % de disponibilité et une expérience utilisateur catastrophique.

Observabilité
Capacité à inférer l'état interne d'un système uniquement à partir de ses sorties externes. Un système observable répond non seulement à "ça marche ?" mais aussi à "pourquoi ça ne marche pas ?" — même pour des problèmes que tu n'avais pas anticipés.

Le terme vient de la théorie du contrôle : un système est observable si son état interne peut être entièrement déterminé depuis ses sorties. En informatique, Charity Majors (Honeycomb) l'a popularisé en 2016 pour décrire ce dont les systèmes distribués ont besoin.

Les trois signaux

L'observabilité repose sur trois types de données que ton système produit en permanence. OpenTelemetry — le standard ouvert de la CNCF — les appelle les signals :

Signal 1
📋 Logs
Signal 2
📊 Métriques
Signal 3
🔗 Traces

Chaque signal répond à une question différente. Ensemble, corrélés via un trace_id commun, ils permettent de comprendre n'importe quel comportement — y compris ceux que tu n'avais pas prévus.

Ce que ce cours couvre

Dans ce cours, tu vas comprendre le rôle de chaque signal, leurs forces et leurs limites, comment les corréler efficacement, les méthodes de mesure (RED, USE, Golden Signals), et une vue d'ensemble du stack open source qui s'est imposé : LGTM (Loki, Grafana, Tempo, Mimir).

📌 Ce cours est la fondation. Les cours suivants de la série approfondissent chaque composant : Prometheus, Loki, OpenTelemetry, et Grafana ont chacun leur cours dédié.
01 — LES LOGS

Les logs : le journal du système

La forme la plus ancienne d'observabilité — et la plus mal utilisée.

Un log est un événement horodaté émis par ton application. C'est le premier réflexe de tout développeur : console.log(), error_log(), logger->info(). Simple, direct, immédiat.

Le problème des logs texte

La plupart des applications produisent encore des logs comme ça :

# Format texte traditionnel
[2024-01-15 14:32:01] app.INFO: User 42 logged in from 192.168.1.5
[2024-01-15 14:32:02] app.ERROR: Payment failed for order #1337 amount=59.99

Ces logs sont lisibles pour un humain mais difficiles à requêter. Pour extraire "tous les paiements échoués supérieurs à 50€ en janvier", tu dois parser du texte libre avec des regex fragiles.

Les logs structurés

La solution : émettre des logs en JSON avec des champs typés et cohérents. Chaque champ devient une colonne que tu peux filtrer, agréger, corréler.

{
  "timestamp": "2024-01-15T14:32:02Z",
  "level":     "error",
  "service":   "payment-service",
  "message":   "Payment failed",
  "trace_id":  "4bf92f3577b34da6a3ce929d0e0e4736",
  "span_id":   "00f067aa0ba902b7",
  "order_id":  1337,
  "amount":    59.99,
  "error":     "card_declined",
  "user_id":   42
}
🔑 Les champs trace_id et span_id sont la clé de la corrélation. Ils permettent de relier ce log à la trace OpenTelemetry correspondante — et donc de voir exactement où dans le chemin d'exécution l'erreur s'est produite.

Les niveaux de log

NiveauUsageExemple
DEBUGDiagnostic détaillé — production désactivéeValeur de variable intermédiaire
INFOÉvénement normal attenduUtilisateur connecté, commande créée
WARNINGSituation anormale mais récupérableRetry réussi après échec, config manquante avec défaut
ERRORÉchec d'une opération — intervention possiblePaiement rejeté, service tiers indisponible
CRITICALÉchec système — intervention immédiateBase de données inaccessible, OOM

Ce que les logs font bien — et ce qu'ils ne font pas

✅ Points forts

Contexte riche et arbitraire. Utiles pour déboguer un cas précis. Faciles à émettre. Conservés longtemps. Idéaux pour les audits.

❌ Limites

Volume énorme en production. Difficiles à agréger (pas de tendances). Coûteux à stocker. Pas adaptés aux questions "combien ?" ou "depuis quand ?".

⚠️ Ne loggue pas tout. En production, INFO+ suffit. Activer DEBUG de façon sélective (par trace_id, par user_id) via le dynamic log sampling est une pratique avancée qui évite de noyer les signaux importants.
02 — LES MÉTRIQUES

Les métriques : la température du système

Des chiffres agrégés dans le temps — parfaits pour détecter, impuissants pour expliquer.

Une métrique est une mesure numérique agrégée dans le temps. Contrairement aux logs qui capturent des événements individuels, les métriques répondent à des questions statistiques : combien ?, à quelle vitesse ?, quel est le 99e percentile ?

Imagine un thermomètre dans ta maison. Il ne te dit pas pourquoi il fait chaud, mais il te dit qu'il fait chaud, depuis combien de temps, et à quelle vitesse la température monte. Les métriques sont ce thermomètre.

Les outils de collecte de métriques

Plusieurs outils existent pour collecter et stocker des métriques. Chacun a son modèle de données, son protocole d'ingestion et ses forces :

OutilModèleParticularité
Prometheus OpenMetrics (pull) Standard de facto cloud-native. Kubernetes natif. Écosystème d'exporters massif.
Datadog Propriétaire (push) SaaS tout-en-un. Corrélation logs/traces/métriques intégrée. Payant.
InfluxDB Time-series (push) Très haute fréquence d'écriture. Langage Flux. Stockage optimisé.
StatsD UDP (push) Ultra-léger, protocole texte. Agrège côté serveur avant envoi.
📌 Dans cette série, le référentiel est Prometheus. Pas parce qu'il est l'unique solution — DataDog ou InfluxDB sont tout à fait légitimes — mais parce que c'est le standard open source de l'écosystème cloud-native (Kubernetes, CNCF), et que le stack LGTM s'en appuie directement. Les concepts décrits ci-dessous (types, labels, cardinalité) viennent du standard OpenMetrics que Prometheus a popularisé, et qu'OpenTelemetry a adopté comme modèle de référence.

Les quatre types du standard OpenMetrics

OpenMetrics définit quatre types fondamentaux, implémentés par Prometheus et alignés avec le modèle OpenTelemetry. D'autres outils ont des équivalents proches, parfois sous des noms différents.

TypeDescriptionExemple
Counter Valeur qui ne fait qu'augmenter. Se remet à zéro au redémarrage. http_requests_total, errors_total
Gauge Valeur qui peut monter ou descendre à n'importe quel moment. memory_usage_bytes, queue_size
Histogram Distribution en buckets préconfigurés. Permet les percentiles. http_request_duration_seconds{le="0.5"}
Summary Percentiles calculés côté client. Moins flexible, éviter en général. rpc_duration_seconds{quantile="0.99"}

Labels et cardinalité

Les métriques ont des labels (ou dimensions) qui permettent de filtrer et d'agréger. C'est là que réside le piège principal.

# Bonne cardinalité : 3 méthodes × 5 codes = 15 séries
http_requests_total{method="GET", status="200"} 1423
http_requests_total{method="POST", status="201"} 89
http_requests_total{method="POST", status="422"} 12

# Cardinalité explosive : 1 série par user_id → des millions de séries
http_requests_total{user_id="42"} 7  ← NE JAMAIS FAIRE
Cardinalité
Le nombre de combinaisons uniques de labels pour une métrique donnée. Une cardinalité élevée crée des millions de séries temporelles — Prometheus explose en mémoire, mais le problème existe dans tous les outils : Datadog facture par série, InfluxDB ralentit. La règle universelle : les labels doivent avoir un ensemble fini et petit de valeurs (statut HTTP, méthode, service, environnement — pas user_id, pas URL complète).

Ce que les métriques font bien — et ce qu'elles ne font pas

✅ Points forts

Légères et compressibles. Idéales pour alerter. Permettent les tendances et corrélations temporelles. Peu coûteuses à stocker longtemps. Parfaites pour les dashboards.

❌ Limites

Aucun contexte sur un événement précis. "Le p99 a monté" ne dit pas quelle requête est concernée. Nécessitent de l'instrumentation préalable — tu ne peux pas poser une question à laquelle tu n'avais pas pensé.

🔑 L'histogram est ton meilleur ami. Pour les latences, utilise toujours un histogram, jamais un average. La moyenne cache les outliers : un p99 à 10 secondes avec une moyenne à 50ms signifie que 1 % de tes utilisateurs souffrent — et tu ne le vois pas dans la moyenne.
03 — LES TRACES DISTRIBUÉES

Les traces : le fil d'Ariane

Quand une requête traverse dix services, une trace te montre exactement où le temps est passé.

Imagine que tu commandes un colis en ligne. Le suivi te dit : "reçu entrepôt Marseille → tri Lyon → livraison Paris → livré". C'est une trace : le chemin complet d'un événement à travers plusieurs étapes, avec le temps passé à chaque étape. Les traces distribuées, c'est exactement ça — mais pour une requête HTTP.

Anatomie d'une trace

Trace
Représentation du chemin complet d'une requête à travers un système distribué, de son entrée jusqu'à sa réponse finale. Identifiée par un trace_id unique (128 bits).
Span
Unité de travail au sein d'une trace. Chaque appel de service, chaque requête SQL, chaque appel HTTP crée un span. Un span a un span_id, un parent, un début, une durée, un statut, et des attributs arbitraires.
// En-tête W3C TraceContext propagé entre services
traceparent: 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01
//           version-{trace_id 32hex}-{parent_span_id 16hex}-{flags}
//           flags: 01 = sampled, 00 = not sampled

Visualisation d'une trace : le diagramme de Gantt

Une trace est visualisée comme un diagramme de Gantt imbriqué, où chaque span est une barre dont la longueur représente la durée. L'imbrication représente la hiérarchie parent/enfant.

Trace ID: 4bf92f35...                              Total: 142ms
├─ api-gateway       GET /orders/42              [0ms ──────────────────── 142ms]
│  ├─ auth-service    ValidateToken               [5ms ───── 18ms]
│  └─ orders-service  GetOrder                    [20ms ──────────────── 142ms]
│     ├─ postgres      SELECT * FROM orders WHERE  [22ms ──── 35ms]
│     └─ postgres      SELECT * FROM order_items    [38ms ──── 98ms]  ← le goulot
🔑 La trace révèle le goulot d'étranglement. Sans trace, tu sais que ta requête prend 142ms. Avec la trace, tu vois que 60ms sont passés sur un SELECT — et tu sais exactement quel service, quelle requête, et dans quel contexte.

Sampling : on ne trace pas tout

En production, tracer 100 % des requêtes est trop coûteux. Le sampling réduit le volume. Deux approches existent :

StratégieDécisionAvantageInconvénient
Head-based À l'entrée de la trace (premier service) Simple, pas de buffering Peut rater les erreurs rares
Tail-based En fin de trace (après collecte complète) Peut garder 100 % des erreurs Nécessite un collecteur avec buffer

Ce que les traces font bien — et ce qu'elles ne font pas

✅ Points forts

Montrent exactement où le temps est passé. Révèlent les dépendances cachées entre services. Indispensables pour déboguer des latences dans les architectures distribuées.

❌ Limites

Nécessitent une instrumentation dans chaque service. Volumineuses — le sampling est obligatoire. Ne montrent pas les tendances dans le temps (pour ça, il faut les métriques).

04 — CORRÉLATION

Corrélation : les 3 piliers ensemble

Un trace_id dans tes logs, c'est la différence entre une heure de debug et dix minutes.

Chaque pilier pris seul est limité. Une alerte de métrique te dit "quelque chose va mal", mais pas quoi. Un log d'erreur te dit quoi, mais pas dans quel contexte global. Une trace te dit le chemin, mais tu ne vois pas les tendances dans le temps.

La puissance de l'observabilité vient de la corrélation entre les trois signaux. Le lien, c'est le trace_id : un identifiant unique généré à l'entrée du système, propagé à travers tous les services, et injecté dans les logs, les traces, et les métriques exemplaires.

Le workflow d'investigation

1. Alerte
📊 Métrique
p99 ↑
2. Identifier
🔗 Trace
trace_id
3. Comprendre
📋 Logs
  1. La métrique alerte : le p99 de latence dépasse 500ms sur orders-service.
  2. La trace identifie : tu trouves les traces lentes, tu vois que 80% du temps est sur un span postgres.
  3. Les logs expliquent : tu ouvres les logs de ce span précis et tu vois slow query: missing index on orders.user_id.
🔑 Sans corrélation, chaque outil est un silo. Grafana permet de passer en un clic d'un spike métrique aux traces correspondantes, et des traces aux logs du même trace_id. C'est ce qu'on appelle le context switching — tu ne changes pas d'outil, tu changes de vue sur le même événement.

Simulateur : observe une requête distribuée

Clique sur "Simuler une requête" pour voir comment les trois signaux sont générés et corrélés.

Requête distribuée — 5 services
💻
Client
🌐
API Gateway
🔐
Auth
📦
Orders
🗄️
PostgreSQL

Lance la simulation pour voir les logs structurés.

Lance la simulation pour voir la trace.

Observe le trace_id commun dans les logs et la trace — c'est lui qui permet de naviguer entre les signaux.

05 — RED, USE & GOLDEN SIGNALS

RED, USE & Golden Signals : quoi mesurer

Observer tout est impossible. Ces trois frameworks te disent ce qui compte vraiment.

L'instrumentation naïve produit des centaines de métriques inutiles et rate les signaux importants. Trois frameworks ont émergé pour répondre à la question : qu'est-ce qu'on mesure vraiment ?

La méthode RED — pour les services

La méthode RED a été proposée par Tom Wilkie chez Weave Works (aujourd'hui Grafana Labs) pour les microservices. Elle dit : pour chaque service, instrumente trois métriques.

LettreSignificationMétrique Prometheus
R — Rate Nombre de requêtes par seconde traitées rate(http_requests_total[5m])
E — Errors Taux de requêtes en erreur (4xx/5xx) rate(http_requests_total{status=~"5.."}[5m])
D — Duration Distribution des latences (p50, p95, p99) histogram_quantile(0.99, ...)
🔑 RED est orienté expérience utilisateur. Si ces trois métriques sont nominales, ton utilisateur est satisfait — même si ton CPU est à 80 %. C'est pour ça qu'elles s'appliquent aux services qui traitent des requêtes (APIs, workers).

La méthode USE — pour les ressources

La méthode USE a été définie par Brendan Gregg (Netflix) pour les ressources physiques et logiques : CPU, mémoire, disque, réseau, connexions de pool.

LettreSignificationExemple
U — Utilization Pourcentage de temps où la ressource est occupée CPU à 75 %, pool de connexions à 60/100
S — Saturation Quantité de travail en attente (queue) Load average, longueur de la queue DB
E — Errors Erreurs matérielles ou logiques de la ressource Erreurs réseau, pages mémoire incorrectes
💡 USE est orienté ressources. Un service peut avoir de bons chiffres RED mais souffrir d'une ressource saturée (pool de connexions BD plein, queue longue). Combiner les deux méthodes donne une vision complète.

Les Golden Signals de Google SRE

Le livre "Site Reliability Engineering" de Google définit quatre signaux dorés que tout service exposé aux utilisateurs devrait surveiller :

Signal 1
Latency
+
Signal 2
Traffic
+
Signal 3
Errors
+
Signal 4
Saturation

Latency : temps pour servir une requête — distinguer succès et erreurs (une erreur rapide ne compte pas comme "bonne latence"). Traffic : charge — requêtes/sec, transactions/sec. Errors : taux d'échecs explicites (5xx) et implicites (200 avec contenu incorrect). Saturation : à quel point la ressource la plus contrainte est proche de la limite.

RED vs Golden Signals
RED = Rate + Errors + Duration ≈ Traffic + Errors + Latency des Golden Signals. Les Golden Signals ajoutent la Saturation, ce qui les rend plus complets. En pratique, les deux sont utilisés et se complètent.
06 — LE STACK LGTM

Le stack LGTM : l'outillage open source

Loki, Grafana, Tempo, Mimir — comment les quatre composants s'articulent.

L'écosystème de l'observabilité open source a convergé autour d'un stack cohérent porté par Grafana Labs. Chaque composant correspond à un signal.

Logs
Loki
+
Viz
Grafana
+
Traces
Tempo
+
Métriques
Mimir
ComposantRôleAlternative
Loki Stockage et requêtage de logs. Indexe uniquement les labels (pas le contenu) — compact et rapide. Elasticsearch, OpenSearch
Grafana Visualisation unifiée. Datasources multiples (Prometheus, Loki, Tempo, Mimir). Alerting. OnCall. Kibana (ELK), Datadog
Tempo Stockage de traces compatible OpenTelemetry, Jaeger, Zipkin. Requêtage par trace_id ou TraceQL. Jaeger, Zipkin
Mimir Prometheus à l'échelle — stockage long terme, multi-tenant, compatible API Prometheus. Prometheus seul, Thanos, VictoriaMetrics

Le collecteur universel : OpenTelemetry Collector

En pratique, tes applications n'envoient pas directement à Loki/Tempo/Mimir. Elles envoient au OpenTelemetry Collector (otelcol), qui reçoit tous les signaux, les transforme si nécessaire, et les route vers les backends appropriés.

# Pipeline OTel Collector (otelcol-config.yaml)
receivers:
  otlp:
    protocols: {grpc: {endpoint: "0.0.0.0:4317"}, http: {endpoint: "0.0.0.0:4318"}}

exporters:
  loki:        {endpoint: "http://loki:3100/loki/api/v1/push"}
  prometheusremotewrite: {endpoint: "http://mimir:9090/api/v1/push"}
  otlp/tempo:  {endpoint: "http://tempo:4317"}

service:
  pipelines:
    logs:    {receivers: [otlp], exporters: [loki]}
    metrics: {receivers: [otlp], exporters: [prometheusremotewrite]}
    traces:  {receivers: [otlp], exporters: [otlp/tempo]}

Alternatives SaaS

Si tu ne veux pas opérer l'infrastructure toi-même, les alternatives managées couvrent le même besoin : Datadog (leader commercial, très complet), New Relic (APM historique, OpenTelemetry natif), Grafana Cloud (stack LGTM hébergé, free tier généreux), Elastic APM (si tu as déjà un cluster Elasticsearch).

⚠️ Le lock-in des agents propriétaires. Instrumenter ton code avec le SDK Datadog te lie à Datadog. Instrumenter avec OpenTelemetry te permet de changer de backend sans toucher au code applicatif. Préfère systématiquement OpenTelemetry.
07 — SYNTHÈSE

Synthèse : construire un système observable

Ce qu'il faut instrumenter en priorité, les pièges à éviter, la feuille de route.

Les trois signaux en un coup d'œil

SignalQuestion à laquelle il répondForcesLimites
Logs "Que s'est-il passé exactement ?" Contexte riche, arbitraire, facile à émettre Volume massif, difficile à agréger
Métriques "Quel est l'état du système dans le temps ?" Légères, alerting, tendances, dashboards Aucun contexte événementiel, cardinalité à maîtriser
Traces "Où le temps a-t-il été passé dans ce chemin ?" Révèle les goulots, cartographie les dépendances Instrumentation nécessaire, sampling obligatoire

Guide de priorités

Si tu pars de zéro, voici l'ordre d'instrumentation recommandé :

  1. Métriques RED sur chaque service HTTP — rate, errors, duration. Minimum vital pour alerter.
  2. Logs structurés avec trace_id — même sans traces actives, le champ te servira plus tard.
  3. Traces sur les chemins critiques — les requêtes qui touchent plusieurs services ou la BD.
  4. Métriques USE sur les ressources — une fois RED en place, ajoute CPU, mémoire, pools.
  5. Corrélation dans Grafana — configure les derived fields Loki → Tempo, et les exemplars Prometheus → Tempo.

Les pièges classiques

Cardinalité explosive. Ne jamais mettre user_id, request_id, URL complète comme label de métrique. Quelques milliers de valeurs distinctes et Prometheus sature.
Logs sans trace_id. Des logs sans corrélation sont des logs dans un silo. Ajoute trace_id dès le premier jour, même si tu n'as pas encore de backend de traces.
Moyennes de latence. La moyenne cache les percentiles élevés. Utilise toujours p95 et p99 — c'est là que souffrent tes utilisateurs.
Agents propriétaires. Instrumente avec OpenTelemetry dès le début. Changer de backend coûte zéro ligne de code applicatif.

La suite de cette série