Observabilité¶
Logs, métriques et traces — les trois piliers pour comprendre ce que fait un système en production.
Monitoring vs observabilité¶
Le monitoring répond à la question "est-ce que le système fonctionne ?". L'observabilité répond a "pourquoi est-ce que le système ne fonctionne pas ?".
Le monitoring est base sur des métriques connues à l'avance : on sait ce qu'on surveille. L'observabilité permet d'investiguer des problèmes imprevus en correlant des signaux de différentes sources. Dans un système distribué avec des dizaines de services, le monitoring seul ne suffit plus — on a besoin de naviguer dans les données pour comprendre une panne qu'on n'avait pas anticipee.
Les trois piliers de l'observabilité sont complementaires :
graph TD
O["Observabilite"]
O --> L["Logs\nEvenements discrets\nQu'est-ce qui s'est passe ?"]
O --> M["Metriques\nValeurs numeriques agregees\nQuelle est la tendance ?"]
O --> T["Traces\nParcours d'une requete\nOu est le goulot ?"]
L -->|trace_id| C["Correlation"]
M -->|alerte| C
T -->|span_id| C
style C fill:#2a9d8f,color:#fff Logs¶
Les logs sont des événements discrets, horodates, qui décrivent ce qui s'est passe dans le système. Un log est une ligne de texte qui capture un fait à un instant donne.
Logs structures (JSON)¶
Les logs non structures (texte libre) sont faciles a écrire mais impossibles a requeter efficacement. Les logs structures en JSON permettent le filtrage, l'agrégation et la correlation automatique.
{
"timestamp": "2026-04-15T10:23:45.123Z",
"level": "ERROR",
"service": "order-service",
"trace_id": "abc123def456",
"span_id": "span789",
"message": "Payment failed",
"error": "timeout after 5000ms",
"order_id": "ORD-42",
"customer_id": "CUST-007",
"payment_provider": "stripe",
"duration_ms": 5023
}
Niveaux de log¶
| Niveau | Usage | Volume attendu |
|---|---|---|
| TRACE | Détail fin pour le debug (parametres, états internes) | Très élevé |
| DEBUG | Information utile au développement | Élevé |
| INFO | Événements métier normaux (commande créée, paiement OK) | Modere |
| WARN | Situation anormale mais gérée (retry, fallback active) | Faible |
| ERROR | Erreur qui impacte une requête ou un utilisateur | Très faible |
| FATAL | Erreur qui empêche le service de fonctionner | Exceptionnel |
En production, le niveau minimal est généralement INFO. DEBUG et TRACE sont actives temporairement pour investiguer un problème spécifique, idealement via un mécanisme de "dynamic log level" qui permet de changer le niveau sans redémarrer le service.
Bonnes pratiques¶
- Toujours inclure un contexte métier —
order_id,customer_id,request_id. Un log sans contexte est inutile pour l'investigation. - Jamais de données sensibles — pas de mots de passe, tokens, numéros de carte. Masquer ou hacher.
- Un log par événement significatif — pas un log par ligne de code. Trop de logs noie l'information.
- Inclure le trace_id — c'est le lien entre logs, métriques et traces. Sans lui, la correlation est manuelle et penible.
Métriques¶
Les métriques sont des valeurs numériques agregees dans le temps. Contrairement aux logs (événements individuels), les métriques représentent des tendances et des distributions.
Types de métriques¶
Counter — valeur monotone croissante. Ne fait qu'augmenter (ou revenir à zero au redémarrage). Exemples : nombre total de requêtes, nombre d'erreurs, octets transferes.
Gauge — valeur qui monte et descend. Capture un état à un instant donne. Exemples : temperature, nombre de connexions actives, taille de la file d'attente.
Histogram — distribution des valeurs observees dans des buckets. Permet de calculer les percentiles (p50, p95, p99). Exemples : latence des requêtes, taille des réponses.
http_request_duration_seconds_bucket{le="0.1"} 24054
http_request_duration_seconds_bucket{le="0.25"} 33023
http_request_duration_seconds_bucket{le="0.5"} 34789
http_request_duration_seconds_bucket{le="1.0"} 35102
http_request_duration_seconds_bucket{le="+Inf"} 35198
Summary — similaire à l'histogram mais calcule les percentiles côté client. Moins flexible (pas d'agrégation entre instances) mais plus précis pour les percentiles exacts.
Méthodes RED et USE¶
Deux cadres complementaires pour instrumenter les métriques :
RED (Request-oriented) — pour les services qui traitent des requêtes :
| Signal | Métrique | Ce qu'elle révélé |
|---|---|---|
| Rate | Requêtes par seconde | Charge, tendance de trafic |
| Errors | Taux d'erreur | Fiabilité du service |
| Duration | Latence (percentiles) | Performance percue par l'utilisateur |
USE (Resource-oriented) — pour les ressources d'infrastructure :
| Signal | Métrique | Ce qu'elle révélé |
|---|---|---|
| Utilization | % d'utilisation de la ressource | Capacité restante |
| Saturation | File d'attente, backlog | Surchargé imminente |
| Errors | Erreurs hardware ou logicielles | Défaillance de la ressource |
RED pour les services, USE pour l'infrastructure. Les deux ensemble couvrent l'essentiel des besoins de monitoring.
Traces¶
Le tracing distribué suit le parcours d'une requête à travers tous les services qu'elle traverse. La ou les logs montrent ce qui s'est passe dans un service, les traces montrent ce qui s'est passe dans le système entier.
Concepts fondamentaux¶
Trace — l'ensemble du parcours d'une requête, de l'entree dans le système jusqu'à la réponse finale. Une trace est composee de spans.
Span — une unite de travail dans un service. Chaque span a un début, une fin, un nom, un statut, et peut contenir des attributs et des événements. Un span peut avoir un span parent (appel imbriquee).
Trace ID — identifiant unique de la trace, propagé à travers tous les services. C'est la clé de correlation.
Span ID — identifiant unique du span dans la trace.
graph TD
subgraph Trace["Trace: abc-123"]
S1["Span: API Gateway\n0-450ms"]
S2["Span: Order Service\n10-400ms"]
S3["Span: Payment Service\n50-350ms"]
S4["Span: DB Query\n60-120ms"]
S5["Span: Stripe API\n130-340ms"]
S6["Span: Notification\n360-390ms"]
S1 --> S2
S2 --> S3
S3 --> S4
S3 --> S5
S2 --> S6
end
style S5 fill:#e76f51,color:#fff Dans cet exemple, la trace montre que l'appel Stripe (130-340ms) est le goulot d'étranglement — il représenté la majorité du temps total. Sans trace, on verrait seulement que l'API Gateway répond en 450ms, sans savoir pourquoi.
Propagation du contexte : W3C Trace Context¶
Le standard W3C Trace Context définit deux headers HTTP pour propager le contexte de trace :
traceparent: 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01
| | | |
v v v v
version trace-id span-id flags
Le header traceparent est obligatoire et contient le trace ID, le span ID du parent, et les flags (sample/no-sample). Le header tracestate est optionnel et permet aux vendors d'ajouter des metadonnees propriétaires.
Échantillonnage (sampling)¶
Tracer 100% des requêtes est coûteux en stockage et en bande passante. L'échantillonnage réduit le volume tout en preservant la visibilité :
| Stratégie | Principe | Cas d'usage |
|---|---|---|
| Head-based sampling | Décision au début de la trace (ex: 10% des requêtes) | Simple, prévisible |
| Tail-based sampling | Décision à la fin (garder les traces lentes ou en erreur) | Cible les cas intéressants |
| Rate-limited | Maximum N traces par seconde | Contrôle du coût |
| Priority-based | Toujours tracer les requêtes critiques (paiements) | Garantie sur les flux importants |
Le tail-based sampling est le plus utile en pratique : on garde toujours les traces en erreur et les traces lentes, qui sont celles qu'on veut investiguer. Les traces normales sont echantillonnees a un ratio plus faible.
Correlation¶
La puissance de l'observabilité vient de la correlation entre les trois piliers. Le trace ID est la clé qui lie tout :
- Une alerte se déclenché sur une métrique (taux d'erreur 5xx en hausse)
- On consulte le dashboard pour identifier le service et la fenêtre temporelle
- On cherche les traces en erreur sur cette fenêtre
- On ouvre une trace pour voir le parcours complet de la requête
- On consulte les logs du span en erreur, filtres par trace_id
graph LR
Alert["Alerte\nmetrique"] -->|fenetre| Dash["Dashboard\nservice + periode"]
Dash -->|requete| Traces["Traces\nen erreur"]
Traces -->|trace_id| Logs["Logs\ndu span"]
Logs -->|cause| Fix["Correction"]
style Alert fill:#c44,color:#fff
style Fix fill:#2a9d8f,color:#fff Sans correlation, chaque pilier est un silo. L'équipe on-call passe des minutes a chercher manuellement les logs qui correspondent à l'alerte. Avec un trace_id dans chaque log, la navigation est immédiate.
OpenTelemetry¶
OpenTelemetry (OTel) est le standard open source pour l'instrumentation. Il unifie la collecte de métriques, logs et traces dans un SDK unique, indépendant du backend de stockage.
Architecture¶
graph LR
App["Application\n+ SDK OTel"] -->|OTLP| Coll["OTel Collector"]
Coll -->|export| Jaeger["Jaeger\n(traces)"]
Coll -->|export| Prom["Prometheus\n(metriques)"]
Coll -->|export| Loki["Loki\n(logs)"]
style Coll fill:#264653,color:#fff SDK — intégré dans l'application. Généré les spans, les métriques et les logs. Disponible en Java, Go, Python, Node.js, .NET, Rust.
Collector — composant intermédiaire qui reçoit, traite et exporte les données de télémétrie. Peut filtrer, enrichir, echantillonner et router les données vers différents backends.
OTLP (OpenTelemetry Protocol) — protocole standard de transport entre le SDK et le collector. gRPC ou HTTP.
Pourquoi OTel plutôt qu'une solution propriétaire¶
| Critère | Solution propriétaire | OpenTelemetry |
|---|---|---|
| Vendor lock-in | Fort | Aucun |
| Changement de backend | Re-instrumenter | Changer l'export config |
| Couverture langage | Variable | Tous les langages majeurs |
| Communauté | Support vendor | CNCF, large communauté |
| Auto-instrumentation | Variable | Riche (HTTP, DB, gRPC) |
L'auto-instrumentation OTel capture automatiquement les spans pour les frameworks courants (Express, Spring, Django, gRPC) sans modifier le code applicatif. Les spans custom sont ajoutes manuellement pour le contexte métier.
Stack d'observabilité typique¶
| Composant | Rôle | Exemples |
|---|---|---|
| Collection | Recevoir la télémétrie | OTel Collector |
| Traces | Stocker et requeter | Jaeger, Tempo, Zipkin |
| Métriques | Stocker et agréger | Prometheus, Mimir, InfluxDB |
| Logs | Stocker et rechercher | Loki, Elasticsearch, CloudWatch |
| Dashboard | Visualiser | Grafana |
| Alerting | Notifier | Alertmanager, PagerDuty, OpsGenie |
Tip
Commencez par les traces. Contrairement à l'intuition, les traces apportent plus de valeur que les logs pour le debugging en système distribué. Un seul trace ID vous montre le parcours complet d'une requête à travers 10 services. Sans traces, vous naviguez entre les logs de 10 services en essayant de reconstruire mentalement le parcours — c'est lent, fragile et souvent impossible sous pression lors d'un incident.
Chapitre suivant : Chaos engineering — provoquer les pannes avant qu'elles ne vous trouvent.