Le diagnostic : Quand trois systèmes isolés deviennent trois angles morts
L'équipe infrastructure de Vertix avait hérité d'une stack typique : Prometheus pour les métriques, ELK pour les logs centralisés, et un début d'implémentation Jaeger pour le tracing distribué. Chaque outil fonctionnait correctement dans son silo. Les dashboards Grafana affichaient des courbes de latence P95 impeccables. Les requêtes Kibana remontaient les exceptions Java. Les traces Jaeger montraient les chemins de requêtes individuelles. Pourtant, lors d'un incident de production, les ingénieurs de garde ouvraient quinze onglets, corrélaient manuellement des timestamps entre trois interfaces, et perdaient vingt minutes à identifier quel service en amont provoquait une cascade de requêtes N+1 vers la base de données. La fragmentation cognitive était le vrai coût. Un système d'observabilité n'est utile que s'il permet de poser une question et d'obtenir une réponse dans la même interface, avec le même contexte de corrélation.
Le point de rupture est survenu pendant un Black Friday. Une augmentation de 340 % du trafic a exposé un goulot d'étranglement dans le service mesh : les handshakes mTLS entre les pods Kubernetes saturaient le CPU des sidecars Envoy, provoquant des timeouts en cascade. Les métriques Prometheus montraient des pics de latence. Les logs indiquaient des erreurs 503. Les traces Jaeger étaient incomplètes car les spans n'étaient pas propagés correctement à travers les appels gRPC. Il a fallu quatre heures et l'intervention de trois équipes pour reconstituer le flux causal. L'équipe plateforme a alors compris qu'elle devait passer d'outils de surveillance à une pratique d'observabilité, où les trois piliers — métriques, logs, traces — partageaient un modèle de données unifié avec des identifiants de corrélation communs.
L'approche : Définir une taxonomie d'observabilité avant de toucher au code
La première décision a été intellectuelle, non technique. L'équipe a organisé un atelier de trois jours pour définir une taxonomie partagée : quels attributs sémantiques devaient être présents dans chaque métrique, log et trace ? Ils ont choisi OpenTelemetry comme fondation conceptuelle, non pas pour remplacer immédiatement tous les agents, mais pour établir un vocabulaire commun. Chaque événement observable devait inclure au minimum : service.name, service.version, deployment.environment, trace.id, span.id, user.id (anonymisé), request.path, et http.status_code. Cette décision a nécessité des compromis difficiles. Les équipes backend ont dû refactoriser leurs bibliothèques de logging maison pour adopter les conventions OpenTelemetry. Les équipes SRE ont accepté une augmentation temporaire de 12 % de l'ingestion de logs pour capturer les attributs de contexte supplémentaires. L'argument était simple : une corrélation fiable valait le surcoût de stockage.
- Adoption d'OpenTelemetry Collector comme point d'agrégation unique pour toutes les données télémétriques, avec des pipelines configurables par équipe.
- Instrumentation automatique via des agents Java, Go et Node.js pour les traces distribuées, réduisant la charge cognitive des développeurs.
- Migration progressive des dashboards Grafana vers des requêtes PromQL enrichies avec des labels OpenTelemetry, permettant des filtres multi-dimensionnels.
- Mise en place d'un RFC document définissant les niveaux de log (DEBUG, INFO, WARN, ERROR, FATAL) et les moments où chaque span devait démarrer et se terminer.
- Création d'un service d'enrichissement de contexte qui injectait automatiquement des métadonnées d'infrastructure (zone de disponibilité, type d'instance, feature flags actifs) dans chaque événement.
- Établissement d'un SLO sur le code review turnaround : toute PR touchant à l'instrumentation devait être revue en moins de quatre heures pour éviter la dérive de standards.
Cette phase de définition a duré six semaines. Certains ingénieurs ont exprimé de l'impatience : pourquoi ne pas simplement déployer un outil tout-en-un comme Datadog ou New Relic ? La réponse tenait à la philosophie de contrôle. Vertix opérait dans un environnement réglementaire strict où les données financières ne pouvaient pas quitter l'UE. Une solution auto-hébergée basée sur OpenTelemetry leur donnait la flexibilité de router les traces sensibles vers un backend interne tout en exportant les métriques agrégées vers un fournisseur SaaS pour l'analyse. La taxonomie n'était pas un exercice bureaucratique ; elle était la fondation contractuelle entre les équipes.
L'implémentation : Du monorepo Bazel aux pipelines de télémétrie
Le monorepo de Vertix utilisait Bazel pour la compilation et le déploiement. L'équipe a tiré parti de cette contrainte pour automatiser l'injection d'instrumentation. Ils ont créé une règle Bazel personnalisée, otel_service(), qui wrappait chaque cible de service avec les agents OpenTelemetry appropriés et injectait les variables d'environnement nécessaires. Toute nouvelle application compilée avec cette règle héritait automatiquement du tracing distribué, des métriques runtime et du logging structuré. Cette approche a réduit le temps d'onboarding d'un nouveau service de deux jours à quinze minutes. Le monorepo, souvent critiqué pour sa rigidité, devenait ici un levier d'homogénéité. En trois mois, 320 des 400 services ont été migrés sans intervention manuelle des équipes produit.
L'observabilité n'est pas un tableau de bord ; c'est la capacité de poser une question que vous n'aviez pas anticipée avant l'incident.
Cette citation, formulée lors d'une rétrospective mensuelle, a guidé la suite de l'implémentation. L'équipe a construit un prototype de "Query Studio" — une interface permettant de composer des requêtes ad-hoc en joignant métriques, logs et traces via des identifiants de corrélation. Par exemple, un SRE pouvait écrire : "Afficher tous les logs ERROR des services ayant une latence P99 supérieure à 500ms sur les 30 dernières minutes, où le feature flag dynamic-pricing est activé, groupés par trace.id." Le backend exécutait cette requête en parallèle sur ClickHouse (pour les logs), Prometheus (pour les métriques) et Tempo (pour les traces), puis enrichissait les résultats avec les métadonnées du service mesh. Ce prototype a résolu l'incident du Black Friday en 18 minutes lors d'une simulation en décembre. L'efficacité provenait non pas de la sophistication algorithmique, mais de la cohérence du modèle de données sous-jacent.
Les défis techniques : Gérer le bruit et l'explosion des cardinalités
L'augmentation de la granularité des données a introduit deux pathologies. Premièrement, l'alerte fatigue s'est intensifiée : avec plus d'attributs, les règles d'alerte mal configurées déclenchaient des faux positifs. Un service pouvait être sain globalement mais afficher des erreurs pour un user.id spécifique dans une région spécifique. L'équipe a dû redéfinir leurs SLIs (Service Level Indicators) en se concentrant sur des agrégations pertinentes : taux d'erreur global, latence P95 par endpoint critique, et disponibilité du service mesh. Les alertes sur des métriques à haute cardinalité (comme les erreurs par user.id) ont été remplacées par des seuils de percentile. Deuxièmement, l'infra cost per active user a augmenté de 9 % en raison du volume accru de spans. Pour compenser, ils ont implémenté un tail-based sampling : seules les traces contenant des erreurs ou dépassant un seuil de latence étaient conservées intégralement, les autres étant échantillonnées à 5 %. Cette stratégie a réduit le coût de stockage de 40 % sans perte de signal critique.
Gouvernance et évolution des runbooks
Un problème insidieux est apparu : les runbooks existants, écrits avant la refonte de l'observabilité, référençaient encore des dashboards obsolètes et des commandes kubectl archaïques. L'équipe a lancé une initiative "Living Runbooks", où chaque procédure d'incident était versionnée dans le même repository Git que le code applicatif et incluait des liens vers des requêtes pré-construites dans le Query Studio. Par exemple, le runbook "Latence élevée du service payment" contenait maintenant un lien cliquable qui ouvrait automatiquement une vue corrélée des traces lentes, des logs d'erreur associés, et des métriques de saturation des ressources. Cette approche a éliminé les stale runbooks, car les liens cassés étaient détectés par des tests automatisés lors du CI/CD.
- Établir un baseline de métriques clés (latence médiane, taux d'erreur, saturation CPU) avant toute migration d'instrumentation, pour mesurer l'impact réel.
- Former les équipes de garde via des game days simulant des incidents complexes, en les forçant à utiliser les nouveaux outils sans accès aux anciennes interfaces.
- Définir un API deprecation timeline pour les anciennes bibliothèques de logging, avec des warnings compilateurs et des alertes Slack automatiques pour les équipes retardataires.
- Négocier avec les fournisseurs de backend (Grafana Labs, ClickHouse Cloud) pour obtenir des quotas d'ingestion flexibles pendant la phase de transition, évitant les surprises budgétaires.
- Documenter les patterns anti-corrélation : situations où joindre métriques et logs via trace.id produisait des résultats trompeurs en raison de différences de timestamps ou de propagation de contexte manquante.
Les résultats quantifiés : De la théorie à la production mesurable
En septembre 2025, six mois après le déploiement complet, Vertix a publié un bilan interne. Le MTTR moyen pour les incidents P1 est passé de 4,3 heures à 1,2 heure, une réduction de 73 %. Le nombre d'alertes hebdomadaires a chuté de 2 300 à 340, car les règles redondantes et les faux positifs ont été éliminés grâce à une meilleure corrélation. Le taux de résolution au premier appel (sans escalade vers une autre équipe) est passé de 48 % à 79 %. Plus subtilement, le feature flag debt count — le nombre de flags obsolètes encore présents en production — a été réduit de 60 %, car l'observabilité permettait désormais de tracer l'utilisation réelle de chaque flag et d'identifier ceux qui n'étaient jamais activés. L'équipe a également mesuré un gain de productivité : les ingénieurs passaient en moyenne 4,7 heures de moins par semaine sur l'investigation d'incidents, temps réalloué au développement de nouvelles fonctionnalités.
Un effet secondaire inattendu a été l'amélioration de la collaboration inter-équipes. Avant la refonte, les débats post-incident dégénéraient souvent en accusations : "Votre service a causé le spike de latence." "Non, c'est votre déploiement qui a introduit un egress NAT mal configuré." Avec une vue unifiée des traces, ces discussions devenaient factuelles. Une trace montrait exactement quel service avait introduit la latence et à quel moment. Les rétrospectives d'incidents sont devenues des sessions d'apprentissage plutôt que des tribunaux. L'observabilité avait transformé la culture autant que l'architecture. Le dernier chiffre révélateur : le turnover dans l'équipe de garde a diminué de 35 %, car les astreintes nocturnes étaient moins épuisantes et les problèmes moins opaques.
Leçons retenues et perspectives d'évolution
La transformation de l'observabilité chez Vertix n'était pas un projet avec une date de fin. C'était un changement de posture intellectuelle : passer de "Nous collectons des données" à "Nous raisonnons sur notre système." Plusieurs leçons se dégagent. D'abord, la standardisation précoce est un multiplicateur de force. Chaque semaine passée à débattre des conventions évite des mois de refactorisation ultérieure. Ensuite, l'automatisation de l'instrumentation via le système de build (Bazel dans leur cas) réduit drastiquement la friction d'adoption. Troisièmement, l'observabilité est un produit interne : elle nécessite des product managers, des roadmaps, et une écoute active des utilisateurs internes. L'équipe plateforme organise désormais des office hours hebdomadaires où les développeurs peuvent poser des questions sur la construction de requêtes complexes ou l'interprétation des traces.
Les prochaines étapes incluent l'intégration de l'observabilité dans les boucles de feedback des déploiements. L'équipe expérimente actuellement avec des circuit breakers automatiques : si une nouvelle version d'un service affiche un taux d'erreur supérieur de 15 % à la version précédente dans les cinq premières minutes, le déploiement est automatiquement annulé et la version précédente est restaurée. Cette approche, parfois appelée "observability-driven rollback", nécessite une confiance totale dans la qualité des signaux. Ils explorent également l'ajout d'une couche de machine learning pour détecter les anomalies de comportement : un service qui fonctionne dans les SLOs mais dont le pattern de latence diffère subtilement de l'historique. Ces pistes prolongent l'argument initial — l'observabilité n'est pas un état final mais une capacité évolutive qui croît avec la complexité du système qu'elle éclaire.