Observabilité et supervision : guide complet pour les équipes techniques

Toutes les équipes supervisent la production. Peu savent répondre à la question « pourquoi le système se comporte-t-il ainsi ? » sans une longue séance de débogage. La différence entre supervision et observabilité n'est pas un choix d'outillage : c'est une philosophie de conception qui détermine à quelle vitesse votre équipe comprend et traite des défaillances qu'elle n'avait pas prévues.

La supervision classique suppose que vous savez quoi surveiller. Vous fixez des seuils de processeur, vérifiez des codes de statut et réveillez quelqu'un quand le disque dépasse 90 %. Cela marche pour les pannes connues. Mais les systèmes distribués modernes échouent d'une manière qu'aucun tableau de bord n'avait anticipée : une légère dégradation de latence dans un service engorge une file d'attente, ce qui se manifeste par l'épuisement du pool de connexions à la base et n'apparaît qu'aux heures de pointe. Sans la possibilité de poser des questions libres sur l'état interne, vous volez à l'aveugle.

Pourquoi l'observabilité dépasse la simple supervision

L'observabilité est la propriété d'un système qui permet d'inférer son état interne à partir de ses sorties externes. La supervision vous dit que quelque chose ne va pas ; l'observabilité vous laisse déterminer ce qui a mal tourné, même pour une défaillance que vous n'aviez jamais imaginée. La distinction est décisive : la supervision est guidée par les alertes et liée aux tableaux de bord ; l'observabilité est guidée par les questions et riche en données.

Quand votre système émet des données structurées à forte cardinalité dans les journaux, les métriques et les traces, vous pouvez corréler des événements, descendre jusqu'à un utilisateur ou une requête précise, et découvrir la cause d'incidents qu'aucune alerte par seuil n'aurait jamais attrapés. Les équipes qui investissent dans l'observabilité réduisent d'un ordre de grandeur leur délai moyen de résolution, parce qu'elles devinent moins et agissent davantage sur des preuves.

« La supervision vous dit si un système fonctionne. L'observabilité vous laisse demander pourquoi il ne fonctionne pas. La seconde est un préalable pour exploiter des systèmes qu'on ne comprend pas entièrement — c'est-à-dire tous les systèmes en production. »

Les trois piliers : journaux, métriques et traces

L'écosystème de l'observabilité repose sur trois types de données complémentaires, chacun avec son rôle. Les traiter comme un signal unifié plutôt que comme des silos séparés, voilà la clé d'un débogage efficace.

Les journaux : traces immuables d'événements

Les journaux sont des enregistrements horodatés d'événements discrets. C'est le signal le plus fin : il capture exactement ce qui s'est produit à un instant donné. Une ligne bien structurée contient assez de contexte — identifiant de requête, nom du service, durée, détail de l'erreur — pour reconstituer le chemin d'exécution sans croiser plusieurs sources.

L'erreur la plus fréquente est de traiter les journaux comme du texte non structuré. Fouiller des fichiers plats fonctionnait avec trois serveurs ; à grande échelle, des journaux non structurés ne sont que du bruit. Chaque ligne doit être analysable, porter des métadonnées structurées et suivre un schéma cohérent dans tous les services de votre architecture.

Les métriques : mesures agrégées dans le temps

Les métriques sont des représentations numériques de l'état du système, relevées à intervalles réguliers. Elles sont conçues pour un stockage économe et une agrégation rapide. Elles répondent à « combien de requêtes par seconde ? » ou « quelle est la latence au 99e centile ? ». Contrairement aux journaux, elles abandonnent le détail de chaque requête : elles échangent la finesse contre la compression et la vitesse.

Les types courants — compteurs, jauges, histogrammes et résumés — servent des usages distincts. Les compteurs suivent des valeurs cumulées, comme le total des requêtes. Les jauges consignent des valeurs instantanées, comme l'occupation mémoire. Les histogrammes répartissent les observations dans des tranches configurables, par exemple pour les distributions de latence. Choisir le bon type évite des agrégations trompeuses et une cardinalité gaspillée.

Les traces : le cycle de vie complet d'une requête

Les traces distribuées suivent une requête unique à mesure qu'elle franchit les frontières entre services. Chaque trace se compose de segments : des opérations nommées, avec horodatage de début et de fin, qui capturent le travail d'un service ou d'une fonction. Les traces sont le seul signal capable de reconstituer le cycle de vie complet d'une requête dans une architecture en microservices.

Sans traces, une page lente pourrait être imputée à n'importe lequel des dizaines de services impliqués. Avec des traces, vous identifiez que le goulot est la requête de base du service utilisateur, qui prend 800 millisecondes, alors que tous les autres segments s'achèvent en moins de 50. Cette précision est hors de portée des journaux ou des métriques seuls.

« Les journaux disent ce qui s'est passé. Les métriques, combien de fois. Les traces, comment tout s'articule. Il faut les trois pour traverser un incident de production sans faire d'hypothèses. »

Mise en place et instrumentation avec OpenTelemetry

OpenTelemetry est le standard du secteur pour produire, collecter et exporter des données de télémétrie. Il offre, d'un langage à l'autre, un ensemble unique d'API et de kits qui émettent journaux, métriques et traces dans un format neutre. L'adopter supprime la dépendance à un fournisseur et garantit que votre instrumentation fonctionne, que vous utilisiez une plateforme commerciale ou une chaîne maison.

Instrumentation automatique ou manuelle

La plupart des kits proposent une instrumentation automatique : des points d'accroche sans code dans les cadres et bibliothèques répandus. Un seul appel d'initialisation peut instrumenter serveurs HTTP, clients de base, files de messages et appels gRPC. L'automatique couvre les chemins courants ; pour le code critique pour le métier, les intergiciels maison et les opérations propres au domaine, l'instrumentation manuelle reste nécessaire.

import { NodeSDK } from "@opentelemetry/sdk-node";
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-grpc";
import { OTLPMetricExporter } from "@opentelemetry/exporter-metrics-otlp-grpc";
import { HttpInstrumentation } from "@opentelemetry/instrumentation-http";
import { ExpressInstrumentation } from "@opentelemetry/instrumentation-express";
import { PgInstrumentation } from "@opentelemetry/instrumentation-pg";
import { Resource } from "@opentelemetry/resources";
import { SEMRESATTRS_SERVICE_NAME } from "@opentelemetry/semantic-conventions";

const sdk = new NodeSDK({
  resource: new Resource({
    [SEMRESATTRS_SERVICE_NAME]: "payment-service",
  }),
  traceExporter: new OTLPTraceExporter({
    url: "http://otel-collector:4317",
  }),
  metricExporter: new OTLPMetricExporter({
    url: "http://otel-collector:4317",
  }),
  instrumentations: [
    new HttpInstrumentation(),
    new ExpressInstrumentation(),
    new PgInstrumentation(),
  ],
});

sdk.start();
process.on("SIGTERM", () => sdk.shutdown());

L'architecture du collecteur OpenTelemetry

Le collecteur OpenTelemetry est un relais neutre qui reçoit, traite et exporte la télémétrie. C'est l'ossature de toute chaîne d'observabilité en production. Déployer un collecteur par hôte, ou en grappe dans votre infrastructure Kubernetes, découple l'instrumentation du choix de destination et permet de regrouper, filtrer, échantillonner et transformer les données avant qu'elles n'atteignent la plateforme.

Les collecteurs peuvent recevoir des processeurs d'échantillonnage en fin de trace : on conserve les traces complètes des requêtes lentes ou en erreur, et l'on écarte l'essentiel du trafic sain. Le coût de stockage chute nettement sans sacrifier la capacité de déboguer précisément les requêtes qui comptent.

receivers:
  otlp:
    protocols:
      grpc:
        endpoint: 0.0.0.0:4317
      http:
        endpoint: 0.0.0.0:4318

processors:
  batch:
    timeout: 1s
    send_batch_size: 1024
  memory_limiter:
    check_interval: 1s
    limit_mib: 512
  filter:
    error_mode: ignore
    traces:
      span:
        - 'attributes["http.target"] == "/healthz"'
        - 'attributes["http.target"] == "/metrics"'
  attributes:
    actions:
      - key: environment
        value: production
        action: upsert

exporters:
  otlp:
    endpoint: "collector.example.com:443"

service:
  pipelines:
    traces:
      receivers: [otlp]
      processors: [memory_limiter, filter, batch, attributes]
      exporters: [otlp]
    metrics:
      receivers: [otlp]
      processors: [memory_limiter, batch, attributes]
      exporters: [otlp]
    logs:
      receivers: [otlp]
      processors: [memory_limiter, batch, attributes]
      exporters: [otlp]

Motifs de journalisation structurée

Journaliser de façon structurée, c'est émettre des entrées dans un format lisible par machine — le plus souvent JSON — avec des noms de champs cohérents d'un service à l'autre. Les journaux cessent d'être un problème de recherche pour devenir un problème de requête. Quand toutes les équipes partagent les mêmes conventions pour les identifiants de requête, les noms de service, les codes d'erreur et les durées, vous pouvez interroger toute votre infrastructure sans écrire d'analyseurs sur mesure.

Concevoir le schéma des journaux

Tout événement structuré devrait comporter un socle d'attributs : horodatage, niveau de gravité, nom du service, identifiant de trace, identifiant de segment et message. Au-delà, ajoutez des champs métier, mais respectez les conventions de nommage. Utilisez par exemple toujours la même graphie, préfixez les champs liés à l'utilisateur de la même façon, et rangez le détail d'une erreur dans un objet imbriqué plutôt que de le concaténer au message.

  • Incluez toujours trace_id et span_id pour corréler journaux et traces
  • Employez un niveau (debug, info, warn, error) qui correspond à des signaux actionnables, pas au confort de la personne qui code
  • Ne journalisez jamais de données sensibles — données personnelles, secrets ou jetons —, même en développement
  • Gardez les messages fixes et mettez les données variables dans des champs structurés, pour pouvoir agréger
  • Uniformisez le format d'horodatage sur tous les services : RFC 3339 ou millisecondes Unix

Pièges fréquents

L'erreur la plus coûteuse est de trop journaliser. Des champs à forte cardinalité, comme les identifiants d'utilisateur ou les adresses IP, peuvent faire exploser le volume de plusieurs ordres de grandeur. Échantillonnez les journaux de débogage volumineux et réservez le détail à certaines traces ou à des conditions d'erreur. Le deuxième écueil est l'incohérence des noms : un service en user_id, un autre en customerId, un troisième en user.id rendent les requêtes transversales impossibles sans couche de transformation.

« Une ligne de journal qu'on ne peut pas interroger pourrait tout aussi bien ne pas exister. La journalisation structurée n'est pas une affaire de lisibilité : il s'agit de faire de chaque entrée une citoyenne de plein droit de votre plateforme d'observabilité. »

Traçage distribué dans les microservices

Le traçage distribué est l'outil le plus efficace pour déboguer une architecture en microservices. Une trace qui traverse vingt services indique exactement où le temps se consume, quelles requêtes échouent et comment les erreurs se propagent. Sans traces, déboguer un tunnel d'achat lent revient à examiner les journaux d'une douzaine de services et à deviner la causalité.

Propagation du contexte de trace

Le contexte de trace doit être propagé à chaque frontière de service : en-têtes HTTP, métadonnées des files de messages, métadonnées gRPC, et jusqu'aux frontières asynchrones comme les tâches planifiées ou les traitements de fond. OpenTelemetry s'en charge automatiquement si vous utilisez ses bibliothèques pour HTTP, gRPC et la messagerie. L'identifiant de trace circule depuis la passerelle d'entrée jusqu'à chaque service en aval, en collectant des segments au passage.

  • Instrumentez tous les points d'entrée : passerelles d'API, répartiteurs de charge, contrôleurs d'entrée
  • Propagez le contexte à travers les files de messages via les en-têtes ou les métadonnées du message
  • Incluez l'identifiant de trace dans la sortie des journaux pour permettre la corrélation
  • Adoptez un échantillonnage qui préserve les traces en erreur ou à forte latence
  • Ajoutez des attributs propres aux segments pour le contexte métier : niveau de client, référence produit, région

Lire et interpréter une trace

Une trace bien annotée révèle le chemin critique d'une requête. Concentrez-vous sur le segment le plus long : c'est votre goulot. Cherchez les segments porteurs d'événements d'erreur ou d'attributs très variés. Comparez les traces des requêtes réussies et échouées pour dégager des motifs. Si les traces montrent systématiquement un appel aval qui dépasse son délai, vous avez un problème de dépendance, pas un bogue applicatif.

Alertes : sur quoi alerter et comment éviter la lassitude

La lassitude face aux alertes est la première menace pour la gestion des incidents. Quand une équipe reçoit cinquante alertes par astreinte, toutes sont ignorées. Le but d'une bonne stratégie n'est pas de détecter chaque anomalie, mais de produire un petit ensemble de notifications à fort signal, qui exigent un jugement humain. Tout le reste relève du tableau de bord ou de la requête.

Le système de niveaux

Classez les alertes en trois niveaux. Le niveau 1 réveille immédiatement la personne d'astreinte, car il signale un problème visible par l'utilisateur : taux d'erreur élevé, indisponibilité totale, ou consommation du budget d'erreur au-dessus du seuil. Le niveau 2 crée un ticket à trier le lendemain ouvré : latence accrue, composants dégradés mais fonctionnels. Le niveau 3 est informatif : certificat proche de l'expiration, limites de stockage en vue.

  • N'alertez que sur des symptômes, pas sur des causes. L'utilisateur voit une erreur 5xx : alertez là-dessus, pas sur l'usage du processeur
  • Utilisez des conditions multiples exigeant une dérive durable avant déclenchement (par exemple cinq minutes au-dessus du seuil)
  • Fixez un maximum de trois alertes réveillantes par personne et par astreinte, pour préserver la qualité du signal
  • Revoyez et élaguez les règles chaque trimestre : des alertes obsolètes rongent la confiance
  • Joignez à chaque alerte le lien d'un guide d'intervention, pour que la personne connaisse les trois premiers gestes

Alerter sur le rythme de consommation

Ces alertes se déclenchent quand votre budget d'erreur se consume plus vite que prévu. Contrairement aux seuils fixes, elles sont directement liées à vos objectifs de niveau de service. Avec un objectif de 99,9 % de disponibilité sur 30 jours, vous disposez d'environ 43 minutes d'indisponibilité. L'alerte se déclenche quand le rythme projeté épuiserait la fenêtre plus tôt que prévu, vous laissant le temps de réagir avant que l'objectif ne soit manqué.

Bâtir des tableaux de bord utiles

La plupart des tableaux de bord sont des cimetières de graphiques inutilisés. Un tableau de bord est utile quand il répond à une question précise sans demander d'interprétation. Les meilleurs sont conçus pour un seul profil et un seul usage : un tableau d'astreinte pour trier les incidents, un tableau hebdomadaire pour la planification de capacité, un tableau d'équipe pour suivre l'atteinte des objectifs.

Le tableau de bord d'astreinte

Il doit tenir sur un écran et répondre à quatre questions : le service est-il debout ? quel est le taux d'erreur ? comment se répartit la latence ? le budget d'erreur est-il dépassé ? Chaque graphique doit porter une ligne de seuil nette, pour qu'on voie tout de suite si la valeur actuelle est saine. Ne mettez pas plus de six graphiques : pendant un incident, la charge mentale compte.

  • Commencez par les métriques RED : débit (requêtes par seconde), erreurs (requêtes échouées), durée (centiles de latence)
  • Ajoutez les métriques USE pour l'infrastructure : utilisation, saturation et erreurs par ressource
  • Affichez l'atteinte de l'objectif et le rythme de consommation comme indicateurs bien visibles
  • Reliez chaque graphique à ses journaux ou à sa requête de traces, pour descendre d'un clic
  • Employez des échelles logarithmiques pour la latence : les échelles linéaires masquent les écarts importants dans les extrêmes

Anti-motifs courants

L'anti-motif le plus répandu est le tableau qui affiche toutes les métriques que produit votre infrastructure. Ces « murs de vert » donnent un faux sentiment de sécurité et rendent impossible de trouver le signal pendant un incident. Autres travers : des camemberts pour des séries temporelles, plusieurs métriques empilées sur des axes incohérents, des lignes de seuil non étiquetées. Si un graphique a besoin d'un commentaire pour être compris, il n'a pas sa place sur le tableau.

SLI, SLO et budgets d'erreur

Indicateurs, objectifs et budgets d'erreur forment le contrat entre votre équipe et vos utilisateurs. Les indicateurs sont les mesures brutes : latence, taux d'erreur, débit. Les objectifs sont les engagements : 99,9 % des requêtes sous 200 millisecondes. Le budget d'erreur est la marge d'échec tolérée — ces 0,1 % qui autorisent l'équipe à livrer, expérimenter et itérer sans craindre de rompre ses engagements.

Choisir des indicateurs qui ont du sens

Un bon indicateur se place du côté de l'utilisateur, se mesure et conduit à l'action. La disponibilité (part des requêtes réussies), la latence (part des requêtes sous un seuil) et la fraîcheur (âge des données servies) sont les plus courants pour un service web. L'essentiel est de mesurer du point de vue de l'utilisateur : une requête que votre serveur résout en 50 millisecondes mais qui prend deux secondes sur un réseau mobile lent est un échec pour la personne qui l'a lancée.

Fixer des objectifs réalistes

Un objectif de 99,999 % impressionne, mais son coût d'ingénierie est énorme. Chaque neuf supplémentaire demande environ dix fois plus d'investissement en redondance, en tests et en outillage d'exploitation. Commencez à 99,9 % pour la plupart des services et réservez davantage aux chemins critiques face au client. Soyez honnête sur ce que vous pouvez tenir : un objectif constamment manqué est pire que pas d'objectif, car il banalise l'échec et ruine la confiance dans les mesures.

Comment le budget d'erreur donne du rythme

Le budget d'erreur transforme la fiabilité, de contrainte en risque mesurable. Quand il est plein, l'équipe livre librement, sachant qu'elle a de la marge. Quand il est épuisé, elle suspend les livraisons non critiques et se consacre uniquement à la fiabilité. On obtient un processus de décision clair, fondé sur les données, qui remplace les débats subjectifs sur le fait qu'une livraison soit « assez sûre ».

Observabilité en sans-serveur et en périphérie

Le sans-serveur et la périphérie posent des défis propres. Les fonctions sont éphémères, l'infrastructure est abstraite, et l'exécution se répartit sur des points de présence répartis dans le monde. La supervision classique par agent ne fonctionne pas : il n'y a pas d'hôte où faire tourner l'agent. Il faut une autre approche : télémétrie poussée depuis le code, traçage fin des démarrages à froid, et gestion prudente de la cardinalité sur des déploiements mondiaux.

Motifs propres au sans-serveur

Le démarrage à froid domine la latence. Instrumentez l'initialisation séparément du traitement de la requête, afin de distinguer la latence de démarrage de celle de la logique métier. Utilisez la journalisation structurée pour capturer le contexte d'invocation — identifiant de requête, région, version de la fonction, environnement d'exécution — et émettez vos métriques de nombre d'appels, de durée et de taux d'erreur de façon asynchrone, pour ne pas bloquer la réponse.

  • Mesurez la durée du démarrage à froid comme métrique propre : elle est invisible dans les métriques standard du fournisseur
  • Utilisez des propagateurs OpenTelemetry compatibles avec le mécanisme d'extension de votre plateforme
  • Exportez la télémétrie par lots pour ne pas alourdir le temps d'exécution de la fonction
  • Mettez en place des métriques dérivées des journaux là où aucune API de métriques n'est disponible
  • Étiquetez toute la télémétrie avec l'environnement, la région et la version de la fonction, pour filtrer efficacement

Particularités de la périphérie

Les plateformes de périphérie exécutent le code sur des dizaines de sites répartis dans le monde. Cette dispersion rend la collecte centralisée classique impraticable. Utilisez des outils pensés pour la périphérie, qui collectent la télémétrie sur chaque site et l'agrègent de façon centralisée à faible coût. Surveillez le taux d'erreur par région : un incident réseau local peut dégrader votre service dans une zone alors que la moyenne mondiale paraît saine.

Bâtir une culture de l'observabilité

Les outils et les chaînes de traitement sont nécessaires mais ne suffisent pas. Le plus difficile, dans l'observabilité, est culturel. Votre équipe doit tenir le code instrumenté en aussi haute estime que le code testé. Chaque nouvelle fonctionnalité devrait inclure l'instrumentation dans sa définition de « terminé », au même titre que les tests unitaires et la relecture. Cela demande de l'infrastructure : bibliothèques partagées, conventions documentées, et dans chaque équipe une personne qui porte le sujet.

Faire de l'observabilité un sujet de premier plan

Commencez par rédiger un document de conception de la télémétrie, qui définit les champs standard, les conventions de nommage des métriques et les exigences de traçage pour chaque service. Intégrez-le au parcours de mise en service de tout nouveau service. Mettez en place dans l'intégration continue des contrôles automatiques imposant un minimum d'instrumentation : rejetez par exemple les demandes de fusion qui ajoutent un gestionnaire HTTP sans traçage ni journal structuré correspondant.

  • Inscrivez l'instrumentation dans la définition de « terminé » de chaque fonctionnalité
  • Organisez régulièrement des journées d'exercice où l'équipe débogue en n'utilisant que tableaux de bord et requêtes de traces
  • Célébrez les réussites : partagez des analyses d'incident qui montrent comment une bonne télémétrie a mené à une résolution rapide
  • Désignez des référents tournants qui vérifient chaque itération la qualité de la télémétrie entre équipes
  • Investissez dans des bibliothèques d'instrumentation partagées, qui rendent le bon geste plus facile que le mauvais

La boucle de rétroaction

L'observabilité n'est pas une mise en place ponctuelle, c'est une boucle continue : instrumenter, livrer, observer, apprendre, améliorer. Quand un incident révèle un angle mort — une métrique non suivie, un champ de journal manquant, une trace perdue —, traitez-le comme un défaut de votre plateforme d'observabilité et corrigez-le. Avec le temps, votre télémétrie se complète, le débogage s'accélère, et l'équipe gagne l'assurance de pouvoir comprendre n'importe quelle défaillance, y compris celles qu'elle n'a jamais vues.

« L'observabilité n'a pas pour but d'empêcher les incidents. Elle a pour but de garantir que, lorsqu'ils surviennent, votre équipe dispose des données, des outils et de l'assurance nécessaires pour les résoudre avant que vos utilisateurs ne s'en aperçoivent. »

Adopter l'observabilité est un cheminement, pas un achat. Commencez petit : instrumentez de bout en bout un service critique, construisez un seul tableau de bord utile, écrivez un objectif de service qui a du sens. Laissez la valeur parler d'elle-même. Une fois que votre équipe aura éprouvé, en plein incident, la différence entre deviner et savoir, elle ne voudra plus revenir en arrière.

See what your own repository can account for.

Thirty minutes on a repository you choose, including the part the record cannot attribute.