Aller au contenu

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étierorder_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.

http_requests_total{method="GET", path="/api/orders", status="200"} 1847293

Gauge — valeur qui monte et descend. Capture un état à un instant donne. Exemples : temperature, nombre de connexions actives, taille de la file d'attente.

db_connections_active{pool="orders"} 23

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
tracestate: vendor1=value1,vendor2=value2

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 :

  1. Une alerte se déclenché sur une métrique (taux d'erreur 5xx en hausse)
  2. On consulte le dashboard pour identifier le service et la fenêtre temporelle
  3. On cherche les traces en erreur sur cette fenêtre
  4. On ouvre une trace pour voir le parcours complet de la requête
  5. 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.