OpenTelemetry ne va pas bien dans votre entreprise. Corrigez-le en 90 jours.

Par Diogo Hudson Dias
Senior engineer reviewing service traces and latency metrics on large monitors in a modern office at dusk.

Votre facture d’observabilité a doublé le trimestre dernier et personne ne trouve la trace de la seule requête qui vous intéresse vraiment. Pendant ce temps, les ingénieurs font encore des grep dans les logs tandis que des milliards de spans partent chez un fournisseur auquel vous ne voulez pas être marié. Si vous avez lu les fils récents « OTel ne se passe pas bien », vous n’êtes pas seul. Le problème, ce n’est pas OpenTelemetry. C’est la façon dont vous l’avez adopté.

Voici un plan de sauvetage sur 90 jours, piloté par les SLO, qui réduit les coûts de 50 à 70 %, met fin aux explosions de cardinalité et rend les traces réellement utiles en gestion d’incident. Il fonctionne pour les monolithes, microservices, serverless et fonctions edge. Il a fait ses preuves dans des SaaS US entre 100 et 10 000 RPS et des stacks polyglottes.

Pourquoi votre déploiement OTel a dérapé

  • Vous avez tout expédié, brut. Faire de l’échantillonnage en tête à 1 % et pousser les spans directement chez un fournisseur, c’est l’illusion de l’adoption et la réalité de la douleur. Les événements en queue n’arrivent jamais. Les chemins critiques sont sous‑représentés. Votre ligne de base n’est que du bruit.
  • La cardinalité a fait exploser vos séries temporelles. Quelqu’un a ajouté user_id, email ou request_path comme labels. Dix labels avec 100 valeurs chacun, c’est 10^10 séries théoriques. Votre backend de métriques a fondu, donc vous avez désactivé les exemplars ou sous‑échantillonné jusqu’à l’inutilisable.
  • La propagation de contexte est cassée là où ça compte. HTTP va bien. Votre passerelle gRPC, le bus de messages, cron et les triggers serverless, non. Les liens parent‑enfant sont rompus ; le baggage véhicule des PII ; les exemplars n’ont pas de point d’ancrage.
  • Aucune gouvernance sémantique. service.name dérive selon les langages. Les équipes inventent leurs propres clés d’attributs. Votre graphe de services est un émoji « haussement d’épaules ».
  • Les logs sont une décharge, pas un pipeline. Tout part en chaud ; rien n’est structuré ; request_id ne relie pas logs, métriques et traces. L’astreinte repose sur la connaissance tribale et la chance.

Vos North Stars (à décider d’abord)

OpenTelemetry n’est que de la tuyauterie. Décidez pourquoi vous l’installez.

  1. SLO de réponse à incident : Vous voulez un p50 MTTR inférieur à 30 minutes et un premier signal utile en moins de 5. Chaque décision de ce plan est évaluée au regard de ces SLO.
  2. Budget de données : Plafonnez à un montant que vous pouvez défendre devant votre CFO. Règle empirique : 0,1–0,3 % du chiffre d’affaires ou 20–50 $ par hôte et par mois. Si vous payez 2–3× plus, vous subventionnez l’entropie.
  3. Parcours « golden » : Choisissez 2–3 parcours qui paient les factures. Ils reçoivent des traces plus riches, 100 % de rétention des erreurs et des exemplars. Tout le reste est traité de manière probabiliste.

Une architecture qui ne vous met pas des bâtons dans les roues

Il existe de nombreuses bonnes options. Celles‑ci fonctionnent dans la réalité actuelle :

  • Mettez toujours un OpenTelemetry Collector au milieu. Les Collectors sont votre plan de contrôle : échantillonnage, nettoyage d’attributs, garde‑fous de cardinalité et routage. Exécutez‑les en DaemonSet sur k8s et en sidecar/VM à l’edge. Voir OpenTelemetry Collector.
  • Échantillonnage en queue plutôt qu’en tête pour le trafic utilisateur en prod. Conservez 100 % des erreurs et des traces lentes. Échantillonnez les traces normales pour tenir un budget. Utilisez tail_sampling avec des budgets par règle et un disjoncteur global.
  • Les exemplars relient métriques et traces. Sans exemplars, vous venez de bâtir deux îles. Utilisez le « span‑to‑metrics » pour peupler RED (Requests, Errors, Duration) et attacher des exemplars aux graphiques principaux.
  • Les logs sont un pipeline à deux niveaux. Chaud (7–14 jours) : logs structurés, au périmètre de la requête ; Froid (90–365 jours) : stockage objet avec recherche à la lecture peu coûteuse. Ne payez pas le prix du chaud pour la rétention de conformité.
  • Choisissez un stockage que vous pouvez vous permettre de garder. Fournisseur ou auto‑hébergé : c’est un choix business. En auto‑hébergé, une pile pragmatique est Grafana Tempo pour les traces, Prometheus/Mimir pour les métriques, et ClickHouse ou Loki pour les logs. Coût de stockage : ~20–30 % de celui des offres managées à l’échelle, avec de l’exploitation à votre charge.

Des chiffres concrets (pour éviter le flou artistique)

Supposons que vous traitiez 10 000 RPS sur dix services. La trace médiane a 10 spans. Un span minimal pèse en moyenne 400–800 octets une fois batché. À 100 % d’échantillonnage, vous écrivez 10 000 × 10 × 600 o ≈ 60 Mo/s, soit ~5 To/jour rien que pour les traces. C’est un cratère budgétaire.

  • Échantillonnez en queue à 5 % (conservez 100 % des 5xx + p95 de latence) : ~250 Go/jour de traces.
  • Supprimez les attributs à forte cardinalité dont vous n’avez pas besoin (user_id, request_path avec paramètres) : réduction de 30–50 % de la taille des spans.
  • Le batching + la compression côté Collector apportent généralement 20–30 % de réduction supplémentaire sur le fil.

Bilan : de 5 To/jour à ~100–150 Go/jour sans perdre ce dont l’astreinte a besoin. C’est 97 % de volume stocké en moins avec un meilleur signal d’incident.

Le plan sur 90 jours

Jours 0–30 : stopper l’hémorragie et poser des garde‑fous

  1. Inventorier et cartographier. Listez chaque charge émettant de la télémétrie par runtime, version, bibliothèque et destination. Capturez ce qui est réellement activé : métriques, traces, logs, profileurs. Attendez‑vous à des surprises.
  2. Insérer une couche de Collector centralisée. Routez toute la télémétrie vers des Collectors régionaux. Activez les processors : batch, memory_limiter, attributes (scrubbing PII), k8sattributes (si sur k8s), et transform pour les corrections sémantiques. Seuls les Collectors parlent aux fournisseurs ou au stockage.
  3. Standardiser l’identité de service. Imposez service.namespace, service.name et service.version dans tous les langages. Cassez les builds non conformes. Sans identité, rien d’autre n’a d’importance.
  4. Tuer le baggage par défaut. Le baggage fuit des PII et explose la cardinalité. Désactivez‑le globalement. Mettez en liste blanche quelques clés minimales et non PII si vous en avez vraiment besoin.
  5. Allowlist d’attributs, pas denylist. Pour les spans et métriques, n’expédiez que les clés approuvées. Démarrez avec : http.method, http.route (templated), http.status_code, db.system, db.operation, messaging.system, net.peer.name (quantized). Supprimez tout ce qui est au périmètre utilisateur.
  6. Plafonnez l’échantillonnage en tête à un niveau raisonnable. Jusqu’à ce que l’échantillonnage en queue soit en production, faites du head sampling à 10–20 % sur les services à fort trafic et à 100 % sur les API peu fréquentées ou d’administration. Conservez 100 % sur les canaries et les environnements de staging internes.
  7. Mettez en place un dashboard « golden path ». Instrumentez de bout en bout 2–3 parcours business clés. Construisez les métriques RED et attachez des exemplars. Ajoutez un panneau « Find Trace » qui fonctionne en 2 clics pendant les incidents.

Jours 31–60 : faire en sorte que les traces répondent aux questions

  1. Activez l’échantillonnage en queue. Dans le Collector, ajoutez des règles : keep if status_code ≥ 500 ; keep if latency ≥ p95 ; keep if release.version is new ; else probabilistic 5%. Définissez des budgets par règle et globaux avec une politique de backpressure (on évacue d’abord le trafic normal).
  2. Propagez le contexte dans les zones « bizarres ». Auditez et corrigez W3C TraceContext à travers gRPC, les bus de messages et les triggers serverless. Pour la messagerie, écrivez traceparent dans les en‑têtes et créez des liens entre les spans producteur et consommateur. Pour cron/batch, démarrez de nouvelles traces et transportez les IDs de corrélation dans les logs.
  3. Des exemplars partout où ça compte. Configurez le span‑to‑metrics pour que les graphiques de latence, d’erreurs et de débit attachent des IDs de trace. Assurez‑vous que votre backend de métriques permet de requêter les exemplars par clic.
  4. Établissez des SLO de cardinalité. À faire respecter : aucune métrique avec une cardinalité de label > 1 000 valeurs uniques/jour ; aucune nouvelle clé de label sans revue de conception ; aucune clé à forte cardinalité sur les métriques « chaudes ». Ajoutez des contrôles CI qui interrogent votre backend pour le churn de séries et font échouer les PR au‑delà des seuils.
  5. Restructurez les logs. Faites de request_id un champ de première classe. Logguez en JSON lignes avec un schéma fixe. Routez les logs chauds (7–14 jours) vers une recherche rapide ; envoyez tout le reste vers du stockage objet avec une couche de requête. Ajoutez des règles de rejet des DEBUG bavards et des health checks au niveau du Collector ou de Vector/Fluentd.
  6. Construisez le premier runbook d’incident propulsé par OTel. Une checklist qui commence sur un dashboard de métriques, saute aux exemplars, ouvre la bonne trace et récupère les logs corrélés via request_id. Chronométrez‑la. Objectif : moins de 5 minutes jusqu’au « premier signal utile ».

Jours 61–90 : verrouiller les coûts, prouver les résultats et automatiser

  1. Mettez des garde‑fous de coût dans le code. Définissez des budgets par service pour les traces (p. ex. 2 Go/jour max), les séries de métriques (max N séries actives) et les logs (Go/jour). Connectez l’autoscaling ou la backpressure dans le Collector pour évacuer les données non critiques quand les budgets sont atteints.
  2. Organisez un game day. Cassez quelque chose de bénin (augmentez la latence sur un service feuille). Mesurez le temps de l’alerte à la cause racine avec et sans exemplars. Attendez‑vous à un diagnostic 2–3× plus rapide quand tout est bien configuré. Si ce n’est pas le cas, ajustez l’échantillonnage ou les exemplars.
  3. Codifiez les conventions sémantiques. Documentez les conventions sémantiques OTel que vous suivez. Fournissez des snippets spécifiques par langage et des linters. Ajoutez une checklist pré‑merge.
  4. Ajustez la rétention à la bonne taille. Traces : 7 jours en chaud, 30 jours en tiède si vous faites des RCA fréquents. Métriques : 18 mois avec sous‑échantillonnage temporel. Logs : 7–14 jours en chaud, 90–365 jours en froid. Si vous ne pouvez pas justifier le jour supplémentaire, ne le payez pas.
  5. Tranchez « fournisseur vs auto‑hébergé » pour l’an prochain. Si vous ne pouvez pas opérer le stockage de façon fiable, achetez‑le. Si votre volume est prévisible et > 200 Go/jour, auto‑héberger Tempo/Mimir/ClickHouse peut coûter 20–30 % d’un fournisseur. Le compromis, c’est la charge SRE. Un pod nearshore focalisé peut combler l’écart avec 20–30 % de coût de main‑d’œuvre en moins que des taux US et 6–8 heures de recouvrement de fuseaux.
  6. Publiez le « contrat d’observabilité ». Une page : SLO, budgets, attributs approuvés, règles d’échantillonnage, règles d’identité de service et runbooks. Traitez les changements comme des ADR.

Des compromis à assumer (pas à éviter)

  • L’échantillonnage n’est pas un péché. Vous ne pouvez pas vous payer 100 % de traces à l’échelle. Vous n’en avez pas besoin. Ce dont l’astreinte a besoin, c’est « garder le mauvais et l’étrange ». L’échantillonnage en queue aligné sur les SLO fait exactement cela.
  • Les logs ne remplacent pas les traces, et inversement. Les traces vous donnent le timing et la causalité ; les logs donnent des faits. Corrélez‑les avec request_id et des exemplars. Si vous ne pouvez pas cliquer d’un pic vers la trace, le travail n’est pas fini.
  • Ne courez pas après la couverture sémantique parfaite. 80 % de conventions cohérentes maintenant valent mieux que 100 % de conformité théorique jamais. Figez les clés, puis itérez.
  • L’observabilité auto‑hébergée n’est pas gratuite. Oui, le coût de stockage chute drastiquement. Non, ça ne tourne pas tout seul. Comptez 0,25–0,5 ETP SRE par 1 To/jour d’ingest pour l’exploitation si vous voulez des SLO sur lesquels parier une semaine d’astreinte.

À quoi ressemble le « bon » au jour 90

  • L’astreinte démarre au même endroit. Un unique dashboard RED avec des exemplars sur lesquels cliquer pour aller aux traces puis aux logs corrélés, sans changer d’outils ni d’onglets.
  • Les coûts sont dans des garde‑fous, pas dans l’espoir. Vous connaissez les Go/jour par type de télémétrie, comment l’échantillonnage les modifie et quand les budgets déclencheront la backpressure.
  • La couverture de traces est intentionnelle. 100 % des 5xx conservées ; les traces lentes p95 conservées ; les requêtes normales échantillonnées à 2–10 % selon la criticité du service. Vous pouvez répondre à « que s’est‑il passé » et « pourquoi maintenant ».
  • La cardinalité est domptée. Aucune métrique avec > 1 000 valeurs de label uniques/jour. Aucune PII dans les attributs. Les données à forte cardinalité vivent dans les logs, pas sur les métriques chaudes.
  • La propagation fonctionne aux frontières qui échouaient avant. Vous pouvez suivre un parcours utilisateur de HTTP → file → worker → serverless sans que la trace s’effondre.

Pièges courants (et comment les éviter)

  • « On fixera l’échantillonnage plus tard. » « Plus tard » n’arrive jamais. Mettez l’échantillonnage en queue dans le Collector d’ici le jour 60 avec des règles et des budgets explicites.
  • Laisser l’autonomie des équipes primer sur l’identité de service. Vous pouvez décentraliser beaucoup de choses. Pas celle‑ci. Cassez les builds qui ne définissent pas correctement service.name.
  • Mélanger des labels bruts au périmètre utilisateur dans les métriques chaudes. Si vous avez besoin d’analytique par utilisateur, c’est un problème de data warehouse ou de ClickHouse. Tenez tout « par utilisateur » hors de Prometheus/Mimir.
  • Courir après 100 % d’auto‑instrumentation. L’auto‑instrumentation aide, mais les spans métiers sur les golden paths demandent du manuel. Donnez aux équipes une recette de 1–2 heures pour « ajouter un span autour de ce cas d’usage ».
  • Envoyer le bruit dev/test vers les backends prod. Routez le non‑prod vers un pipeline séparé. Mieux : supprimez‑en la majeure partie. L’observabilité doit refléter la prod, pas les tests unitaires.

Un mot sur la conformité et la confidentialité

OTel attire les PII si vous êtes négligent. Traitez la gouvernance des attributs comme un contrôle de confidentialité :

  • Supprimez les identifiants utilisateur à l’edge. Si un cas d’usage les exige vraiment, hashez ou regroupez, et documentez la politique de rétention et d’accès.
  • Nettoyez les secrets dans le Collector. Ajoutez des processors qui caviardent les bearer tokens, clés API et emails avant stockage. Ne comptez jamais sur les équipes applicatives pour « se souvenir ».
  • Auditez. Des requêtes mensuelles pour détecter des motifs de PII dans les attributs et les logs. Si vous ne pouvez pas prouver que le nettoyage a fonctionné, c’est qu’il n’a pas fonctionné.

Checklist d’outillage utilisable dès demain

  • Processors du Collector : batch, memory_limiter, tail_sampling, attributes (drop/redact), transform (normalize attributes), k8sattributes, spanmetrics, probabilistic_sampler (pour les services à faible trafic), resourcedetection.
  • Dashboards : RED par service ; graphe global des services ; SLO par parcours avec budgets d’erreurs ; « Find Trace » avec filtres service.name, http.route, status_code et release.version.
  • Runbooks : 1) Démarrer au panneau SLO. 2) Cliquer l’exemplar. 3) Inspecter le chemin critique de la trace. 4) Sauter vers les logs pour request_id. 5) Capturer la timeline. 6) Décider rollback vs mitigation.

OpenTelemetry est le bon pari. La douleur initiale n’est pas un verdict ; c’est le signal que vous avez installé des tuyaux sans décider ce que vous vouliez y faire circuler. Donnez à vos équipes une boussole, mettez le Collector aux commandes, et budgétez selon les SLO, pas à l’instinct. Dans 90 jours, vous aurez des coûts plus bas, des réponses à incident plus rapides et un système que les ingénieurs d’astreinte utilisent vraiment.

Points clés à retenir

  • Décidez d’abord de vos SLO et de vos budgets ; reliez‑y chaque choix OTel.
  • Mettez l’OTel Collector au milieu et passez à l’échantillonnage en queue d’ici le jour 60.
  • Imposez l’identité et les sémantiques : service.name, service.namespace, service.version sont non négociables.
  • Utilisez les exemplars pour relier métriques et traces ; faites de « Find Trace » une action en 2 clics.
  • Cappez la cardinalité : allowlist d’attributs, baggage tué par défaut, et contrôles CI.
  • Restructurez les logs en chaud structuré + froid économique ; corrélez via request_id.
  • Verrouillez les coûts avec des budgets de données par service et de la backpressure côté Collector.
  • Attendez‑vous à 50–70 % de réduction des coûts et un diagnostic 2–3× plus rapide une fois réglé.

Ready to scale your engineering team?

Tell us about your project and we'll get back to you within 24 hours.

Start a conversation