En tant que consultant, il m'est commun d'apporter de l'expertise ponctuelle dans des projets. J'interviens dans des projets dont je n'ai pas assisté à la genèse (et pour lesquels j'espère ne pas voir la fin non plus). Je prends le train en marche, et mon premier ressenti est souvent de faire face à une boîte noire.
Pour pallier mon déficit d'information, je peux alors me pencher sur des éléments de documentation (idéalement, vivants) produits par l'équipe responsable du système avant mon arrivée. Mais je constate en pratique qu'il n'y a rien de plus efficace pour comprendre un système que de l'observer pendant qu'il fonctionne : pouvoir appuyer sur un bouton et observer quels rouages de la machine tournent, ou ne tournent pas.
Récemment, une de ces casquettes d'expertise que j'ai eue à porter est celle d'expert en performance, pour aider un client à améliorer la latence de son système distribué. Avant mon intervention, on m'avait assuré que le système était observable, ce qui allait faciliter mon intervention.
Posons une définition de ce terme, tirée du livre Observability Engineering (Charity Majors, Liz Fong-Jones, George Miranda, 2022) :
💡 Observabilité
Un système logiciel est dit "observable" si les humains qui interagissent avec lui sont capables de comprendre ses états internes sans avoir besoin de livrer une nouvelle version de ce système.
(Note : dans ce qui suit, le terme “simulation” est un terme métier : une simulation est réalisée par des chercheurs R&D qui se servent de données issues de mesures expérimentales)
Lors de mon premier jour à interagir avec ce système, j'étais en mesure de le stresser : je pouvais lancer un ordre pour exécuter, via un endpoint HTTP, une simulation dite "lourde" (durée de traitement approximative de 13h).
Je me suis naturellement rendu dans la solution d'observabilité utilisée par l'équipe pour observer le système pendant cette simulation, et j'ai fait face à une situation à laquelle je ne m'attendais pas : les requêtes que je saisissais dans l'interface produisaient soit aucun log, soit trop de logs, et je ne comprenais pas ce que le système faisait.
L'équipe a configuré ses microservices de manière à remonter tout ce qu'elle pouvait dans son puits de logs : logs de requêtes HTTP, logs techniques des différents frameworks frontends et backends, logs des bases de données, logs systèmes des services sur les machines virtuelles, logs applicatifs rédigés par les développeurs dans le code, ... Tout était là, et en tant que nouvel arrivant sur le projet, je me sentais submergé.
Pour les besoins de ma mission, j'étais intéressé par répondre à de simples questions, par exemple :
Le système produisait des logs, il y en avait beaucoup, ils remontaient bien dans la solution d'observabilité (d'ailleurs, certains remontaient même en double 👯), mais pour autant je trouvais que la solution d'observabilité en l'état ne remplissait pas sa fonction car je ne trouvais pas réponse à mes questions, et l'équipe en charge du projet non plus, d'ailleurs. Paradoxalement, une observabilité trop détaillée a rendu le système moins observable.
Ce système est-il observable ?
⚠️ Le paradoxe du bruit
Des logs qui n’obéissent pas à une stratégie de logging claire créent du bruit et rendent le système métier moins observable. Dans ce cas, plus on ajoute d'observabilité, plus on ajoute de bruit et moins le système est observable.
Pour sortir du brouillard, j’ai proposé à l'équipe qui opère le système de réaliser un atelier eventstorming, dans sa forme la plus simple (le format "Big Picture") pour se focaliser sur le processus métier qui nous intéresse. L'objectif : identifier les événements métier réellement significatifs pour permettre au néophyte que j’étais de comprendre ce qu'il se passe.
En 1h30 d'atelier, avec le tech lead et un sachant métier, nous avons identifié les événements clés du processus de simulation. En voici une version épurée :
(Note : dans un eventstorming, les post-its oranges 🟧 désignent des événements importants qui se produisent dans le système étudié, les post-its bleus 🟦 désignent des commandes envoyées à ce système. L’enchaînement de post-its produit un narratif qui se lit temporellement de gauche à droite dans les schémas plus loin, ou de bas en haut dans l’énumération qui suit - voici un lien pour ceux qui souhaitent en savoir plus sur cet exercice de modélisation collaborative qu’on retrouve fréquemment dans la boîte à outils des pratiquants du Domain-Driven Design)
🟦 Request a Simulation - L'utilisateur (un chercheur R&D) ordonne une simulation (via une UI)
🟧 Simulation Requested - La demande de simulation est réceptionnée par l'API de calcul
🟧 Simulation Parameters Validated - Les paramètres sont vérifiés
🟧 Simulation Started - Le traitement, réalisé par un worker, commence effectivement
🟧 Data Loading Completed - Les données nécessaires à la simulation sont chargées
🟧 Computation Started - Le cœur du calcul démarre
🟧 Intermediate Result Computed - Résultat intermédiaire (répété N fois)
🟧 Intermediate Results Persisted - Les résultats intermédiaires sont sauvegardés (répété N fois)
🟧 Post-processing Computation ended - Des post-traitements sont appliqués sur les données produites par la simulation
🟧 Calculation Phase Completed - Le calcul est terminé (côté backend)
🟧 Simulation Completed - La simulation est terminée (le frontend peut être notifié)
A la fin de l'atelier, nous avions sous les yeux une trame d'événements, un narratif construit collectivement pour modéliser ce que le système est censé faire.
💡Remarque
Tout le monde dans la pièce était aligné avec le contenu sur le mur de post-its. Tout le monde, sauf le code : aucun de ces événements métier n'apparaissait clairement ni dans le code ni dans les logs de l'application.
L'équipe a par la suite décidé d'ajouter de nouveaux logs dans le code, en miroir de l'eventstorming.
Les étapes de la simulation surgissent, en miroir de l'eventstorming
💡Remarque-bis
L’ajout de logs n’est pas toujours aisé dans tous les systèmes. L’eventstorming a mis en évidence ici que le flow de contrôle dans le code n'était pas exactement aligné sur le flow de l'eventstorming. Dans certaines situations, l’histoire racontée par le code peut en effet diverger, à tort, par rapport au modèle mental imaginé par les concepteurs du système. Ici, l’équipe a choisi dans un premier temps d’ajouter des logs pour marquer les début et fin des traitements qui composent la simulation. Une fois la simulation plus observable et la root cause des problèmes de performance identifiée, un refactoring a pu être priorisé pour ré-aligner le code avec la modélisation issue de l’eventstorming.
Chez les clients chez qui j’interviens, l’observabilité est souvent soit absente, soit prise très au sérieux mais très centrée sur des aspects techniques. Les discussions tournent principalement autour des outils (quelle solution on achète ou déploie), et, selon moi, pas assez sur ce que je vais appeler ici l'observabilité métier.
💡 Observabilité métier
En complément de la définition de l'observabilité posée plus tôt : l'observabilité métier, c'est pouvoir observer les opérations métier réalisées par un système : comprendre ce que les utilisateurs essaient d'accomplir, pouvoir vérifier le respect (ou non) des invariants métier, pouvoir vérifier le bon respect de niveaux de service (SLA) métier.
L'obsession pour les métriques techniques peut nous faire perdre de vue ce qui compte vraiment. Voici quelques recettes que j'essaie d'appliquer dans mes projets pour rendre le métier plus observable, en concevant ma stratégie de logging autour de l'eventstorming.
Un post-it orange = 1 point d'observation métier critique = 1 log dans le code
Orienter sa stratégie de logging de manière à ce que n'importe qui dans l'équipe, idéalement votre PO, puisse répondre à des questions essentielles sur le fonctionnement du système.
⚠️ Disclaimer
Il y a des limites à se servir d’outils d’observabilité pour prendre des décisions où le coût de l’erreur est élevé (ex: comptabilité, facturation, santé, …). Ces outils n’offrent généralement pas de garantie sur l’exactitude, la complétude ou la consistance des données qu’elles affichent. Des compromis sont faits pour favoriser la vitesse d’exécution ou limiter le coût de stockage de la donnée : donnée échantillonnée et donc incomplète, ou bien supprimée au bout d'un certain nombre de jours.
Exemples de questions sur le volet "produit"
Emergence de modèles de lecture (post-its verts) dérivés des événements pour mieux comprendre le rapport des utilisateurs au produit
Exemples de questions sur le volet "performance"
Je viens de lancer une simulation qui porte l'ID 7CDEFF5B-9CB5-45BB-B6DF-7E0DD6B06DBA et j’aimerais caractériser le comportement du système avant de chercher à réaliser de quelconques optimisations.
Je viens de réaliser un patch sur le code de la simulation : j’ai changé 1 ligne de code impliquée dans la sauvegarde des résultats intermédiaires en base de données. Je formule l’hypothèse (falsifiable) que ce patch va améliorer le temps de traitement. Je lance donc une nouvelle simulation qui porte l’ID 26C2399B-8845-485D-9B81-A420384B0366.
Exemples d’invariants métier sur la simulation, entendus à l’oral lors de discussions et lors de l’eventstorming
Toutes ces questions (produit, performance, réglementaire, métier, ...) doivent pouvoir trouver une réponse si les événements importants sont logués.
Il est bien sûr possible de trouver réponse à ces questions sans faire tout cela. Mais pour prendre un autre exemple sans doute plus parlant, je trouve cela plus pratique de reconstituer un parcours d'achat ou le cycle de vie d'une police d'assurance en me basant sur des logs qui racontent une histoire métier explicite avec des termes signifiants, plutôt qu’en faisant de la rétro-ingénierie sur la signification de logs de requêtes HTTP.
🧩 Observer son système métier ne devrait pas être un escape game.
Si cet article vous a intéressé, je vous proposerai dans une seconde partie d’aborder des façons d’implémenter cette stratégie de logging en miroir de l’eventstorming, dans le code. On évoquera sans doute des mots bizarres mais importants tels que: pipes and filters, Middleware ou encore CommandBus 🤓.
Pour les lecteurs qui souhaitent aller plus loin