Hope is not a strategy

– Expression traditionnelle d’un SRE (https://sre.google/sre-book/introduction/)

Table des matières

Qu’est-ce que l’observabilité ?

Les systèmes techniques mis au point par les développeurs sont tous créés dans le but de générer de la valeur ajoutée, et par extension, rapporter de l’argent.

Or, une fois en production, un système technique qui rapporte de l’argent, c’est un système technique qui tourne !

Pas un système indisponible toutes les 10 minutes, pas un système dont les résultats sont tantôt valides, tantôt en erreur sans que l’on sache pourquoi, ni un système dont les temps de latence sont tels que les clients le fuient, ou l’utilisent par dépit.

C’est là que l’observabilité rentre en ligne de mire. En effet, pour affirmer qu’un système technique fonctionne comme attendu, il faut savoir ce qu’il fait. Et c’est en observant son comportement qu’on sait ce qu’il fait.

L’observabilité, c’est “l’outil qui permet d’affirmer qu’un système est actif ou non et, lorsqu’il est actif, de déterminer s’il fonctionne correctement ou fait preuve d’une défaillance.”

L’idée générale de l’observabilité est apparue en 1960 avec Rudolf E.Kalman, notamment via son étude sur la théorie des systèmes et du contrôle. En quelques mots, Rudolf suggère que si vous surveillez les sorties d’un système, vous aurez une idée assez précise de ce qu’il se passe à l’intérieur et de pourquoi cela fonctionne comme il le fait.

Mais l’importance du sujet n’a été saisie que 20 ans plus tard, probablement suite à la 1er panne majeure d’internet (Arpanet) le 27 octobre 1980. Le résumé et l’analyse de cet incident ont été documentés dans la RFC 789.

Désormais, c’est un sujet incontournable ! 90% des responsables IT indiquent que l’observabilité est critique pour le succès de leur business. Mais il reste encore du travail, sachant que seulement 33% ont achevés la mise en place d’une observabilité full-stack (aka. observabilité de bout-en-bout, c’est-à-dire la capacité de voir tout ce qui peut affecter l’expérience du client au sein de l’ensemble de la stack technique).

Source : New Relic Observability Forecast 2022 et 2023.

Bien orchestrée, l’observabilité peut répondre à différentes problématiques techniques :

  • “Mes micro-services sont-ils tous up ?” : détermine si le système est actif ou non
  • “La dernière mise à jour provoque-t-elle des crashs/latences dans le traitement de données ?” : détermine si le fonctionnement est nominal ou si une régression est en cours

Mais aussi à des problématiques fonctionnelles, voir business :

  • “Combien d’utilisateurs s’inscrivent par jour ?” : permet de savoir si la fréquentation reste stable
  • “Quel est le temps de traitement moyen par typologie de données entrantes ?” : permet d’affiner les offres commerciales en fonction des usages

L’observabilité est une partie importante du travail d’un SRE (Site Reliability Engineer). C’est l’outil quotidien qui lui permet d’assurer le bon déroulement des systèmes dont il est responsable.

Pourquoi c’est important ?

Dans les pratiques SRE, les principales responsabilités des ingénieurs logiciels et des opérationnels sont de construire et d’améliorer la fiabilité du système et de le faire de manière simple et efficace.

Pour atteindre cet objectif, les équipes SRE surveillent généralement de manière proactive leurs services afin d’identifier les domaines nécessitant une inspection plus approfondie. Cette surveillance proactive permet à l’équipe de prendre des décisions sur les problèmes importants et de hiérarchiser leurs gravités. Cela permet de créer une feuille de route pour améliorer le système, et permet d’être factuel sur son état de santé, plutôt que de simplement espérer que celui-ci soit en bonne forme.

Le monitoring est un élément essentiel des pratiques SRE. C’est souvent le point de départ de la gestion de la fiabilité globale d’un système et de ses services. A l’aide de tableaux de bord visuels et d’alertes automatisées, l’équipe peut garder un œil sur tout ce qui est inhabituel.

Enfin, en consolidant les données de monitoring reçues des différents services qui composent votre système, il devient possible d’élaborer une stratégie de surveillance efficace, visant à améliorer le temps de détection (TTD, aka. Time To Detect) et le temps de résolution (TTR, aka. Time To Recovery) global de votre système technique, s’assurer que vous êtes en accord avec vos SLO/SLA (aka. Service Level Objective et Service Level Agreement) et limiter les impacts financiers ainsi que le ressenti négatif de vos clients en cas d’incident.

Pour résumer, c’est important parce que :

  • La fiabilité du système peut être tracée et son évolution budgétée dans le temps
  • Ça réduit le temps de détection (TTD) en permettant d’être prévenu au plus tôt des dysfonctionnements
  • Ça réduit le temps de résolution (TTR) en fournissant les bonnes indications aux personnes chargées de résoudre les situations problématiques.

Comment ça fonctionne ?

Dans les équipes en charge de l’observabilité des systèmes, on retrouve fréquemment la mise en place de MELT et LETS.

MELT - Bonnes pratiques logicielles

MELT est un acronyme décrivant un ensemble de 4 bonnes pratiques logicielles, visant à intégrer de l’instrumentation dans les applicatifs. Il s’agit de bonnes pratiques que les ingénieurs logiciels doivent inclure le plus souvent possible dans les logiciels qu’ils produisent.

Découvront la signification des 4 lettres qui composent cet acronyme.

MELT - M pour Metrics

Une métrique est une mesure numérique dans le temps.

Elle peut décrire un statut à un instant donné, par exemple “Disque dur rempli à 87%”, ou un agrégat de mesures, par exemple “372 messages reçus de ServiceA sur les précédentes 15 minutes”.

Le type d’agrégation dépend du besoin (somme, moyenne, minimum, maximum…).

Enfin, quel que soit le type de métrique, elles partagent toutes ces 3 propriétés :

  • Un nom
  • Un horodatage
  • Au moins une valeur numérique

MELT - E pour Events

Un événement est la représentation d’un fait unitaire, résultant d’une action à un moment précis.

Plus complets que les métriques, les événements sont représentés dans des formats d’échanges standardisés : JSON, XML, Avro

De manière générale, les événements possèdent à minima ces 3 propriétés :

  • Timestamp : le moment, au format UTC, où l’événement a été levé par le système
  • EventType : le type de l’événement, permettant de le discriminer parmi d’autres événements
  • Data : les données fonctionnelles associées à l’événement

Toutes les autres propriétés sont généralement des métadonnées servant à enrichir le contexte dans lequel l’événement survient.

Pour mieux représenter ce qu’est un événement, on peut imaginer les événements levés par une prise éléctrique connectée. Prenons un ensemble d’événements émis lorsqu’un appareil est branché ou débranché, qui permettrait à son fabricant de mieux déterminer le cycle de vie de ses équipements en lui transmettant des données relatives à l’usage de ce dernier et à l’utilisateur d’avoir des informations sur la consommation réelle de ses appareils.

Ici, un exemple de ce que pourrait être l’événement au format JSON lors du branchement d’un appareil sur la prise :

{
    "timestamp": "2023-08-03T22:35:21.676Z",
    "eventType": "Legrand.ElectricalSocket.Device.Plug",
    "deviceId": "e2b198a1-9115-43d9-84b2-d0c3a4be09be",
    "id": "dee4d165-5d61-430f-b6c3-8ead6802f02b",
    "data": {
        "direction": "in",
        "consumption": 25.78,
        "power": 800
    }
}

Considérations relatives à l’usage des évènements

On voit souvent des équipes faire du “full-event” par défaut au démarrage de nouveau projet, et ainsi se focaliser uniquement sur ce moyen pour faire transiter de l’information.

Il ne faut pas oublier que la collecte et le stockage des événements ont un coût. En effet, chaque événement nécessite une certaine capacité de calcul pour être collecté, traité puis stocké. Et concernant le stockage, il ne faut pas perdre de vue qu’ils peuvent aussi prendre de la place dans votre base de données (potentiellement beaucoup de place !).

Donc, pour des choses relativement peu fréquentes, comme le branchement ou le débranchement d’un appareil, les événements sont parfaits ! Ils permettent de faire transiter de manière unitaire des informations fonctionnelles.

En revanche, émettre et collecter des événements pour tout ce que doit gérer la prise éléctrique peut s’avérer inutile, voir entrainer une surconsommation de ressources. Par exemple, disons que l’on souhaite garder un historique de la consommation des appareils branchés sur la prise.

Il serait possible d’émettre un événement pour chaque détection de changement de puissance. Or, avec un capteur qui détecte au dixième de watt les variations de puissance, il est probable que plusieurs milliers, voire millions, d’événements soient levés chaque jour. Ce qui viendrait rapidement remplir une base de données avec une granularité des données pas forcément utile.

A l’inverse une bonne stratégie pour ce type de données serait de prélever un échantillon de la puissance à un intervalle régulier et de le transmettre. Ce type de données est mieux stocké comme métrique.

Afin de mieux cerner quand utiliser les métriques ou les événements, voici un tableau récapitulatif :

Avantages Inconvénients
Evènements Inclus des points de données individuels Coûteux pour stocker de gros volumes de données d’événements
Permet de se poser toutes les questions que l’on veut, à tout moment Peut rencontrer des contraintes liées à la bande passante du système source lors de la collecte et de l’envoi des événements
Peut-être calculé à la volée Peut prendre du temps à interroger
- - -
Métriques Stocke beaucoup moins de données Nécessite de décider comment analyser les données à l’avance
Prends moins de temps pour calculer les agrégats

MELT - L pour Logs

Il n’est pas exagéré de dire que les logs, journaux en français, sont le type de données à l’origine de l’observabilité.

Dans leur forme la plus fondamentale, les journaux ne sont essentiellement que des lignes de texte issues d’un système lorsque certains blocs de code sont exécutés. Et les développeurs comptent beaucoup sur eux pour déboguer et vérifier rétroactivement l’exécution de leur code !

En réalité, les journaux sont extrêmement précieux pour le dépannage des systèmes techniques, qu’il s’agisse de bases de données, caches, load-balancer ou même des systèmes legacy et/ou propriétaires qui ne sont pas compatibles avec les autres techniques d’instrumentation décrites dans cet article.

Comme pour les événements, les données des journaux sont unitaires, c’est-à-dire qu’elles ne sont pas agrégées. Cependant, les journaux sont généralement beaucoup plus granulaires que les événements. Il n’est pas rare d’émettre plusieurs logs dans une fonction logiciel, pour ne finalement lever qu’un seul événement à la fin d’un traitement.

Attention cependant à ne pas les négliger, ni en termes de quantité, ni de qualité.

Comme indiqué précédemment, pour de nombreux systèmes le format de journaux par défaut est la journalisation textuelle (un texte brut), qui a l’avantage d’être facilement lisible par les humains, mais dont l’interaction avec les machines est plus difficile.

La journalisation structurée est la pratique consistant à implémenter un format de message cohérent et prédéterminé pour les journaux d’application qui leur permet d’être traités comme des ensembles de données plutôt que comme du texte. L’idée de la journalisation structurée consiste à prendre un journal d’application fourni sous la forme d’une chaîne de texte et à le convertir en un ensemble de données relationnelles simple pouvant être recherché et analysé plus facilement.

Voici un exemple de journalisation textuelle et son résultat :

var segment = new Segment(new (1, 4), new(6, 8));
var length = segment.GetLength();
logger.LogInformation($"The length of segment {@segment} is {length}.");

/*
Résultat : 
2023-08-03T22:35:21.676Z|INFO|The length of segment [[1,4][6,8]] is 7.
*/

Voici un exemple de journalisation structurée et son résultat :

var segment = new Segment(new (1, 4), new(6, 8));
var length = segment.GetLength();
logger.LogInformation(
    "The length of segment {@segment} is {length}.",
    segment,
    length
);

/*
Résultat : 
{
    "@t": "2023-08-03T22:35:21.676Z",
    "@mt": "The length of segment {@segment} is {length}.",
    "segment": {
        "Start": {
            "X": 1,
            "Y": 4,
            "$type": "Point"
        },
        "End": {
            "X": 6,
            "Y": 8,
            "$type": "Point"
        },
        "$type": "Segment"
    },
    "length": 7
}
*/

MELT - T pour Traces

Les traces, ou plus précisément les “traces distribuées”, sont des échantillons de chaînes d’événements (ou de transactions) entre différents composants d’un écosystème de micro-services ou de services distribués. Et comme les événements et les journaux, les traces sont unitaires et irrégulières.

Les traces qui sont reliées ensemble forment des événements spéciaux appelés “spans”. Les traces et les spans sont tous identifiés via des identifiants uniques.

Les traces et spans aident à suivre une chaîne causale à travers un écosystème de services pour une seule transaction. Pour ce faire, chaque service se transmet des identifiants de corrélation, appelés “trace context”. Ce contexte est utilisé pour ajouter des attributs sur les “spans” et ainsi suivre le parcours d’une transaction à travers un système technique.

Voici l’affichage résultant du suivi d’une trace distribué réalisé avec l’outil Jaeger :

La capture d’écran ci-dessus montre une FunctionApp (service Serverless sur Microsoft Azure) récupérer des données de météo, puis les transmettre à travers un EventHub à une autre application chargée d’ingérer et transformer les données reçues.

On distingue bien les 2 couleurs (marron et jaune) réparties par application, ainsi que la liste des logs émis sur le span (affichés uniquement pour le span principal ici).

Si vous voulez en savoir plus sur le tracing distribué, je vous invite à lire cet excellent article de New Relic.

LETS - Surveiller proactivement son système

LETS, parfois appelé “4 Golden Signals”, est un acronyme décrivant un ensemble de 4 métriques à surveiller pour déterminer si un système est dans son état nominal.

Ces “4 signaux dorés” sont les éléments de base à la mise en place d’une stratégie de surveillance efficace, et participent activement à l’amélioration du temps de détection (TTD) et du temps de résolution (TTR).

Découvrons la signification des 4 lettres qui composent cet acronyme.

LETS - L pour Latency

La latence est la métrique qui indique le temps qu’il faut à un système pour répondre à une requête.

Il est essentiel de faire la différence entre la latence des requêtes réussies et échouées. Par exemple, une erreur HTTP 500, déclenchée en raison d’une perte de connexion à la base de données, peut être servie rapidement. Cependant, étant donné que le code d’erreur HTTP 500 indique l’échec de la demande, sa prise en compte dans la latence globale peut entraîner des résultats trompeurs. Et paradoxalement, une erreur lente peut être encore pire car elle prend en compte encore plus de latence.

Pour éviter ce genre de désagrément, la mesure de la latence doit donc se faire selon plusieurs axes : les requêtes réussies, les requêtes en échec pour raison fonctionnelle et les requêtes en échec pour raison technique.

LETS - E pour Errors

La métrique « erreur » correspond au taux de requêtes qui échouent sur le système.

On catégorise généralement ces erreurs de la manière suivante :

  • Explicite : par exemple, une erreur interne du serveur (HTTP 500)
  • Implicite : par exemple, une réponse de réussite (HTTP 200) associée à un contenu inexact
  • Par politique : par exemple, si votre temps de réponse maximal est défini sur « 1 seconde », toute requête qui prend plus d’une seconde est considérée comme une erreur

Les équipes SRE doivent surveiller toutes les erreurs à travers le système technique ainsi qu’à des niveaux de services individuels, afin de définir quelles erreurs sont critiques et lesquelles sont moins graves. En identifiant cette criticité, elles déterminent la santé de leur système du point de vue de l’utilisateur et peuvent prendre des mesures rapides pour corriger les erreurs fréquentes.

LETS - T pour Trafic

La métrique « trafic » mesure la demande qui pèse sur votre service de la part des utilisateurs.

Sa définition dépend du type de système que l’on surveille, par exemple :

  • Pour une API Web, la mesure du trafic va correspond aux nombres de requêtes HTTP par seconde que l’API subit
  • Pour un système de stockage, le trafic peut correspondre aux transactions par secondes ou un type particulier d’opération par seconde
  • Pour une file d’attente (aka. message queue), cela peut correspondre à la quantité d’éléments en attente de traitement

C’est en surveillant l’interaction des utilisateurs et le trafic dans le service, que les équipes SRE déterminent si l’expérience utilisateur avec le système est correcte, et dans quelle mesure elle est affectée par les changements/montée en charge.

LETS - S pour Saturation

La métrique de « saturation » fait référence à la capacité globale du service, ou autrement dit, à quel point le service est « occupé » à un moment donné.

Cela correspond généralement à la quantité de CPU ou de mémoire que votre système utilise. De manière générale, les systèmes techniques commencent par sous-utiliser leur capacité d’utilisation, avant d’atteindre les 100% d’utilisation.

Par conséquent, la définition d’un objectif d’utilisation est essentielle car elle contribuera à :

  • Garantir les performances et la disponibilité du service pour les utilisateurs en cas de forte utilisation
  • Minimiser les coûts associés aux matériels/services en cas de sous-utilisation

Une augmentation de la latence est souvent un indicateur annonciateur de saturation. Mesurer votre temps de réponse au 99ème percentile sur une courte période peut fournir un indicateur précoce de saturation. Par exemple, une latence au 99ème percentile de 60 ms indique qu’il y a un délai de 60 ms pour chacune des 100 requêtes.

MELT vs LETS ?

“We cannot understand the world without numbers, and we cannot understand it with numbers alone”

– Hans ROSLING (du livre “Factfulness : Ten Reasons We’re Wrong About the World and Why Things Are Better Than You Think”)

Bien que LETS se base majoritairement sur les métriques de MELT pour visualiser l’état du système, il est important de ne pas se concentrer uniquement sur la consommation de métriques, au point d’en délaisser les événements, les traces ou les journaux.

Si les événements et les traces distribuées sont plus intuitivement mis en place dans des systèmes distribués, il ne faut pas omettre leur valeur ajoutée, que ça soit pour des motifs d’audit/historisation du fonctionnement d’un système ou surveillance des flux.

Quant aux journaux, bien que généralement plus verbeux, ils sont les plus à même de nous offrir l’insight nécessaire à la compréhension d’une défaillance du système.

Avantages et inconvénients

La mise en place d’une politique d’observabilité d’un système permet d’obtenir 2 principaux gains :

  1. Assurer un fonctionnement pérenne du système sur le long terme, et cela, que ce soit en pics de charge ou à la suite de mises à jour du système. À travers des pratiques SRE, notamment LETS, il devient plus factuel de s’assurer que tout fonctionne correctement
  2. Faciliter les interventions des équipes en cas de défaillances :
    • Un accès à des logs structurés, la possibilité de visualiser les événements du système, suivre le parcours d’une requête sur l’intégralité du système via ses traces…
    • Il s’agit là d’éléments vitaux pour permettre une intervention rapide et efficace des équipes en cas de défaillances

En revanche, atteindre une maturité opérationnelle sur les pratiques SRE peut s’avérer challengeant sur certains aspects :

  1. Les connaissances techniques et connaissances métiers :
    • L’élaboration de métriques tenant compte des spécifications métiers et/ou spécifications d’implémentation est un sujet délicat
    • Il est nécessaire de définir au plus tôt, lors de la conception, les lignes directrices de la surveillance à mettre en place sur un système, pour ne pas se retrouver à mesurer des éléments qui ne risque pas de lever d’alertes, ou à l’inverse, qui passeront leur temps à provoquer de faux positifs
  2. L’outillage :
    • Choisir le bon outil, peut s’avérer complexe. Un bon nombre d’outils, payant/gratuit, open-source/closed-source, self-hosted/managés existent. Chacun avec leurs avantages et inconvénients. Choisir le bon dépendra de vos besoins et vos capacités
  3. Le temps/coût d’exploitation :
    • La surveillance d’un système n’est pas quelque chose que l’on met en place et qu’on oublie. Il convient de la regarder fréquemment, pour s’assurer que le système fonctionne correctement, mais aussi pour s’assurer qu’on le surveille selon les bons axes
    • Les pratiques SRE prennent du temps, et donc, de l’argent. Mais elles sont nécessaires pour s’assurer que le système fonctionne bien. Sans elles, on ne peut qu’espérer que tout se passe bien 😉

Et maintenant, comment je fais ?

Après avoir abordé la théorie, j’espère vous avoir convaincu (si ce n’était pas déjà le cas) que l’observabilité est indispensable dans une application. Désormais, vous devez probablement avoir envie d’en savoir plus sur les solutions à disposition pour instrumenter vos applications.

Nous allons commencer par parler de la norme dominante de télémétrie puis nous allons passer en revue les outils back-ends permettant d’exploiter ces données.

Let’s go !

OpenTelemetry

OpenTelemetry est un projet open source (sous la responsabilité de la CNCF, Cloud Native Computing Foundation) regroupant des APIs, des SDKs et des outils pour aider les développeurs à créer, superviser et exporter des données de métriques, traces ou logs vers des back-ends d’observabilité, via un format unique et unifié. Il fait suite à la fusion de OpenTracing et OpenCensus.

En terme de taille, il s’agit du second plus gros projet de la CNCF, après Kubernetes.

L’avantage numéro 1 est l’indépendance. Open Telemetry étant un standard (du moins, il est en passe de le devenir), on va pouvoir passer d’un outil d’observabilité à un autre à tout moment, avec seulement de légères modifications. Avant, il fallait utiliser les agents des fournisseurs pour collecter les données de télémétrie. Mais leur utilisation pouvait vous lier à ces fournisseurs.

Le second avantage, qui découle du premier, est la flexibilité et le choix dans la solution d’instrumentation.

OpenTelemetry s’articule autour de 4 piliers :

  • des spécifications : soit les protocoles standards ouverts
  • des bibliothèques d’instrumentation et des SDKs: spécifique à un langage pour permettre l’implémentation d’OpenTelemetry. C’est ce qui va être utilisé pour instrumenter les applications et générer des données. Il en existe dans de nombreux langages, comme C++, C#/.NET, Go, Java, Javascript, PHP, Python ou encore Rust
  • un collecteur : système recevant, traitant et transmettant les données en provenance des bibliothèques vers les back-ends d’observabilité (en mode agent, embarqué dans l’applicatif, ou en mode collecteur, qui est un service propre)
  • des exportateurs : pour permettre la transmission des données vers les back-ends de votre choix
OpenTelemetry - https://opentelemetry.io/img/otel-diagram.svg OpenTelemetry - https://opentelemetry.io/img/otel-diagram.svg

Dans le cas de .NET, voici la procédure pour intégrer OpenTelemetry dans votre application.

Pour les logs, vous devez installer les 2 packages suivants :

Vous devez ensuite modifier votre fichier Program.cs pour activer la collecte des logs :

var builder = WebApplication.CreateBuilder(args);
builder.Logging.ClearProviders();
builder.Logging.AddOpenTelemetry(logging => 
{
    logging.IncludeScopes = true;
    var resourceBuilder = ResourceBuilder
        .CreateDefault()
        .AddService(builder.Environment.ApplicationName);
    logging.SetResourceBuilder(resourceBuilder)
        .AddConsoleExporter();
});

var app = builder.Build();
app.Logger.StartingApp();
app.Run();

Dans cet exemple, j’ai utilisé l’exporter Console. C’est idéal pour comprendre comment tout fonctionne et pour faire des tests. Dans un environnement de production, il est conseillé d’utiliser l’exporter OLTP.

Regardons maintenant du côté des métriques et des traces. On va avoir besoin d’un package supplémentaire : OpenTelemetry.Instrumentation.AspNetCore.

Comme pour les logs, on va ensuite modifier le fichiuer Program.cs :

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddOpenTelemetry()
    .ConfigureResource(resource => resource
        .AddService(serviceName: builder.Environment.ApplicationName))
    .WithMetrics(metrics => metrics
        .AddAspNetCoreInstrumentation()
        .AddConsoleExporter())
    .WithTracing(tracing => tracing
        .AddAspNetCoreInstrumentation()
        .AddConsoleExporter());

var app = builder.Build();
app.Run();

Pour aller plus loin, je vous invite à consulter le GitHub de l’implémentation .NET d’OpenTelemetry.

Les back-ends d’observabilité

Une fois vos applications instrumentées, il est nécessaire de mettre en place un outil permettant d’exploiter ces données. C’est là qu’interviennent les back-ends d’observabilité.

Il existe sur le marché de nombreux outils pour vous aider dans cette tâche.

Attention, cette liste n’est évidemment pas exhaustive ! J’ai fait le choix de mettre le focus sur quelques outils, mais il en existe d’autres qui peuvent rendre des services similaires.

Lors de votre choix, il me semble important de porter une attention particulière aux points suivants :

  • options de déploiement
  • facilité de mise en oeuvre (SDK, configuration…)
  • extensibilité
  • support des standards
  • support de votre stack technique

Concernant les options de déploiement, il existe essentiellement 2 modes :

  • self-hosted : il s’agit de solutions que l’on doit déployer et installer par soi-même sur une infrastructure (on-premise ou cloud). Il est donc nécessaire d’avoir des compétences avancées dans différents domaines. En revanche, cette complexité permet d’obtenir un meilleur contrôle ainsi qu’une personnalisation plus poussée.
  • managé : il s’agit de solution “clé en main” pour lesquelles vous payez pour un service. Les problématiques d’hébergement, de gestion et de disponibilité ne vous concernent pas, et vous n’avez qu’à vous préoccuper de la configuration.

Les solutions managées sont pertinentes, notamment grâce à la rapidité et la simplicité de mise en œuvre. Néanmoins, les composantes coût et extensibilité sont moins intéressantes.

Azure Monitor

Proposée par Microsoft, il s’agit de son outil de monitoring pour la plateforme Azure. Composé de plusieurs sous-services, Azure Monitor est une solution complète servant à collecter, analyser et agir sur les données de télémétrie en provenance de vos environnements, qu’ils soient dans le cloud et sur site.

À travers ses sous-services, la surveillance obtenue par Azure Monitor peut aller de l’état d’une VM (CPU, mémoire, disque, …) jusqu’à la mesure et l’alerte sur les temps de réponse d’une WebApp, en passant par la levée de métrique personnalisée et l’analyse approfondie de logs.

Avec Azure Monitor, vous pouvez utiliser le SDK Application Insights ou la distribution OpenTelemetry d’Azure Monitor.

Malgré l’investissement de Microsoft dans cette norme et son appétence pour l’open source, la parité des fonctionnalités entre le SDK et la distribution n’est pas encore atteinte. Dans le cas de .NET, la distribution est encore en préversion publique et ne dispose pas de l’ensemble des fonctionnalités. Vous trouverez plus d’informations dans la FAQ de Microsoft.

Pour le code à écrire, la documentation Microsoft est très bien faite, je vous laisse la consulter ;)

Sentry

Sentry.io est un système de suivi des erreurs, full-stack et open source.

Ce système vous permet de suivre en temps réel les erreurs survenues dans vos logiciels, avec le détail complet de la pile d’appel lors de la levée de l’erreur, ce qui s’avère très pratique pour les développeurs puisque ça leur permet d’obtenir l’insight suffisant pour comprendre l’origine et les circonstances de la survenue d’une erreur.

Bien que son éditeur mette en avant son offre managée en ligne, il est tout à fait possible de l’auto-héberger, et ainsi tirer profit de sa propre infrastructure.

Du côté de Sentry, le support d’OpenTelemetry est désormais disponible globalement. Il est intégré sur les SDK NodeJS, NextJS, Python, Ruby, Java, .NET et Go.

La logique d’intégration dans votre code C# est similaire à Azure Monitor. Il suffit d’ajouter les bons exporters et d’ajouter la configuration qui va bien (notamment votre DSN).

Si vous souhaitez utiliser Sentry dans le cadre d’une application .NET, c’est par ici que ça se passe !.

Prometheus / Loki / Grafana

Ce trio est composé d’outils open source ayant chacun un rôle distinct dans la collecte et l’analyse de journaux et de métriques :

  • Prometheus :
    • Il collecte les données sur les serveurs (mode “pull”), puis les stocke.
    • Les métriques sont stockées sous forme de données de séries chronologiques (aka. “time series data”)
    • Les métriques stockées sont horodatées, à la date à laquelle elles ont été enregistrées dans Prometheus
    • Les métriques peuvent aussi être accompagnées des paires clé-valeur, facultatives, appelées “labels”
  • Loki :
    • Il s’agit d’un agrégateur de journaux, inspiré de Prometheus
    • Il est conçu pour être économique et facile à utiliser
    • Contrairement à une base de données comme ElasticSearch (pour ne citer qu’elle), Loki n’indexe pas le contenu des journaux, mais plutôt un ensemble de “labels” pour chaque flux de journaux (à la Prometheus)
  • Grafana :
    • Il s’agit d’un outil open source permettant de construire des tableaux de bord et des graphiques, depuis plusieurs sources de base de données temporelles
    • S’intègre nativement avec Prometheus et Loki
    • Il ne collecte et ne stocke aucune donnée, il se contente de les afficher

Avec Prometheus, OpenTelemetry est largement supporté et il existe un exporter en .NET permettant de se brancher simplement dessus. Il s’agit de OpenTelemetry.Export.Prometheus.AspNetCore.

Pour Loki, vous pouvez utiliser Serilog qui propose un sink permettant l’export vers Loki.

L’avantage de cette solution réside dans sa flexibilité :

  • Tout peut être collecté et affiché selon vos besoins et envies
  • Vous définissez la période de rétention des données en fonction de vos besoins, cela permet d’optimiser les coûts de stockage des données

Jaeger et Zipkin

Jaeger est un système de traçage distribué écrit en Go. Il a été créé par Uber, et s’inspire de Zipkin et Google Dapper. Depuis 2017, il fait parti de l’écosystème CNCF. Jaeger est bâti sur un architecture moderne, lui offrant une bonne fiabilité et évolutivité.

Zipkin est un peu plus ancien (2012) et a été initié par Twitter. Il s’agit d’une application en Java. De part son ancienneté, Zipkin dispose d’une architecture moins modulaire et plus centralisée. Dans le cas de petit projet, ce n’est pas très important. Mais cela peut devenir un problème si votre système commence à croitre et à devoir scaler, car les performances de Zipkin vont être affectées.

Ils offrent tous les deux une solution complète permettant de visualiser les interactions entre service, d’identifier les goulots d’étranglement et de résoudre les problèmes de performance. Le choix dépendra donc essentiellement de votre stack technique et de la dimension de vos applications.

Conclusion

J’espère que cet article vous aura convaincu que l’observabilité est un sujet important, et même indispensable, dans une application (et en particulier dans le cadre d’une application distribuée).

Pour résumer, cela passe par des pratiques (MELT et LETS notamment), de l’outillage et un certain niveau de maturité technique et fonctionnelle pour vos équipes.

Cela permet à vos équipes de développement d’avoir des informations pour comprendre et diagnostiquer les problèmes plus rapidement (en temps réel ou à posteriori), et donc d’améliorer la fiabilité et la disponibilité (et par extension, obtenir une meilleure expérience utilisateur).

Garder à l’esprit la norme OpenTelemetry, il s’agit d’un must-have dans votre projet d’observabilité.

Dans les mois à venir, on va probablement voir l’intégration de plus en plus importante des fonctionnalités AI/ML (aka. intelligence artificielle et machine learning), notamment pour la détection d’anomalie ou l’automatisation de l’agrégation de certaines données. C’est un sujet d’avenir, et je ne manquerais pas de vous en reparler prochainement ;)

Enfin, je remercie Emilien Guilmineau pour son aide à la rédaction de cet article ;)