CodeGym /Cours /C# SELF /Surveillance des performances et collecte des métriques

Surveillance des performances et collecte des métriques

C# SELF
Niveau 64 , Leçon 3
Disponible

1. Introduction

Imaginez que vous êtes admin d'un site, et que chaque jour mille utilisateurs arrivent. Dans les logs vous voyez que tout marche, presque pas d'erreurs (au mieux quelqu'un oublie parfois son mot de passe ou se trompe sur le captcha). «Tout va bien !» — vous vous dites.

Et puis soudain quelqu'un contacte le support : le site est hyper lent, les pages mettent 10 secondes à s'ouvrir. Vous allez voir les logs — pas d'erreurs ! Super ? Non, parce que les logs racontent ce qui s'est passé (ou pas), mais ne disent pas à quel point c'était rapide ou lent, combien de ressources ça a pris, et comment ce comportement a évolué avec la charge.

C'est là que les métriques entrent en scène — ce sont des caractéristiques mesurables du fonctionnement de l'application. Ce n'est pas seulement le nombre d'erreurs, mais aussi le temps de réponse moyen, la quantité de mémoire utilisée, le nombre de requêtes par seconde et d'autres indicateurs pour juger de la santé du système.

Comparaison :
Les logs — c'est "ce qui s'est passé".
Les métriques — c'est "à quel point le système fonctionne bien/mal".
La trace — c'est "pourquoi le système fonctionne comme ça (en détail)".

Quels types de métriques existent, et quoi collecter ?

Principaux types de métriques :

Type de métrique Exemple À quoi ça sert
Compteurs (Counters) Nombre de requêtes, d'erreurs, de pannes Tendances, alertes, charge
Histograms Temps de réponse, taille de paquet Distribution des valeurs, percentiles
Gauges (Gauge) Utilisation mémoire, CPU État courant d'une ressource
Sommes (Sum) Volume total de données, octets Volume total d'opérations sur une période

Exemples :

  • Moyenne et 95ᵉ percentile du temps de réponse pour les requêtes GET.
  • Nombre d'utilisateurs en ligne en ce moment.
  • Utilisation mémoire (Private Bytes, Working Set).
  • Fréquence des erreurs de type 500/503.
  • Requêtes vers la base en une minute.

Ces indicateurs permettent non seulement de détecter des problèmes, mais aussi de les prévenir — une charge serveur en hausse ou une augmentation lente du temps de réponse peuvent annoncer des pannes futures.

2. Comment est construite la collecte des métriques dans .NET et l'écosystème OpenTelemetry

Architecture générale

Dans le .NET moderne (à partir de .NET 6, surtout en .NET 8/9) il existe un système standard de collecte de métriques basé sur OpenTelemetry.

Voici comment ça fonctionne :

  1. Le code de l'application appelle des méthodes pour incrémenter des compteurs, enregistrer des gauges, écrire dans des histograms.
  2. Le SDK OpenTelemetry Metrics collecte ces métriques (en mémoire) et les envoie périodiquement.
  3. L'exporter de métriques les transmet vers le système de monitoring choisi (Prometheus, Application Insights, Grafana Cloud, Datadog, etc.).
  4. Le backend de monitoring agrège, stocke, visualise, crée des alertes et des dashboards.
Schéma simplifié :

[Votre application] 
       ⬇ 
 [Collecte des métriques (OpenTelemetry SDK)]
       ⬇
 [Exporter de métriques (Prometheus, AI, Datadog, ...)]
       ⬇
 [Système de monitoring/dashboards/alertes]

3. Pratique : Bases du travail avec les métriques en C#

Métriques internes simples : System.Diagnostics.Metrics

.NET fournit un mécanisme intégré pour les métriques — System.Diagnostics.Metrics.

Acteurs principaux : Meter, Counter<T>, Histogram<T>, ObservableGauge<T>.

Exemple : compteur de visites de la page


// On crée le Meter (généralement un pour toute l'appli)
using System.Diagnostics.Metrics;

static Meter meter = new Meter("MyCompany.MyApp", "1.0");

// On enregistre le compteur
static Counter<long> homePageVisits = meter.CreateCounter<long>("HomePageVisits");

// Quelque part dans le contrôleur ou le service...
public void HomePageRequested()
{
    homePageVisits.Add(1);
    // Suite du code de traitement de la page
}

Commentaires :

  • Meter — c'est la "factory" pour les métriques, avec un nom unique (espace de noms de l'appli/entreprise).
  • CreateCounter<long> — crée un compteur ; incrément via Add(1).

Exemple : mesurer le temps de réponse


static Histogram<double> pageLoadTime = meter.CreateHistogram<double>("PageLoadTimeMs");

// Dans le handler de requête :
public void OnRequest()
{
    var stopwatch = System.Diagnostics.Stopwatch.StartNew();

    // ...ici la requête elle-même...

    stopwatch.Stop();
    pageLoadTime.Record(stopwatch.Elapsed.TotalMilliseconds);
}

Collecter des gauges pour des valeurs dynamiques

Un gauge est une métrique qui varie dans le temps : nombre d'utilisateurs connectés, volume mémoire courant, etc.


static ObservableGauge<int> onlineUserGauge = meter.CreateObservableGauge(
    "OnlineUsers", 
    () => GetOnlineUserCount());

// Où GetOnlineUserCount est une méthode qui renvoie la valeur actuelle
static int GetOnlineUserCount()
{
    // Ici mettez votre vraie logique !
    return ActiveUserList.Count;
}

Dans la vraie vie tout ceci fonctionne de façon asynchrone : l'application fournit les valeurs des métriques, et l'exporter les récupère et les envoie à l'extérieur (par exemple, Prometheus scrape l'endpoint "/metrics").

Ajouter des métriques dans une application ASP.NET Core moderne

Pour ASP.NET Core beaucoup de choses sont disponibles out-of-the-box. Il suffit d'ajouter le package OpenTelemetry.Instrumentation.AspNetCore, et vous aurez des métriques HTTP, temps de réponse, nombre d'erreurs, etc.

Exemple de configuration dans Program.cs :


using OpenTelemetry.Metrics;
using OpenTelemetry.Resources;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddOpenTelemetry()
    .WithMetrics(metrics =>
    {
        metrics
            .SetResourceBuilder(ResourceBuilder.CreateDefault().AddService("MyApp"))
            .AddAspNetCoreInstrumentation() // métriques HTTP
            .AddRuntimeInstrumentation()    // métriques runtime .NET CLR
            .AddProcessInstrumentation()    // CPU/mémoire du process
            .AddMeter("MyCompany.MyApp")    // vos métriques
            .AddPrometheusExporter();       // export vers Prometheus
    });

var app = builder.Build();

app.MapGet("/", () => "Hello World!");

app.Run();

Maintenant votre appli exposera les métriques à l'adresse /metrics, que Prometheus ou d'autres systèmes peuvent scrapper.

4. Exemples pratiques d'utilisation des métriques

Surveillance des performances dans des projets réels

On branche les métriques pour savoir :

  • Quel RPS moyen et pic (requests per second) l'API supporte ?
  • Où sont les goulets d'étranglement : un endpoint prend 300 ms, un autre — 2000 ms ?
  • Combien de temps passent les appels vers la DB ? (on ajoute nos propres histograms)

Exemple : on surveille le temps des requêtes DB


static Histogram<double> dbQueryDuration = meter.CreateHistogram<double>("DbQueryDurationMs");

public async Task<List<Product>> GetProductsAsync()
{
    var sw = Stopwatch.StartNew();
    var result = await _db.Products.ToListAsync();
    sw.Stop();
    dbQueryDuration.Record(sw.Elapsed.TotalMilliseconds);
    return result;
}

Exemple : on compte le nombre d'erreurs


static Counter<long> apiErrors = meter.CreateCounter<long>("ApiErrors");

public IActionResult SomeEndpoint()
{
    try
    {
        // une action quelconque
        return Ok();
    }
    catch (Exception)
    {
        apiErrors.Add(1);
        throw;
    }
}

Travailler avec les labels (tags) pour les métriques

Il est important de regrouper les données par des attributs utiles : endpoint, type d'erreur, type d'utilisateur, etc.


homePageVisits.Add(
    1, 
    KeyValuePair.Create<string, object>("UserType", "Admin"));

Ou pour un histogram :


dbQueryDuration.Record(
    sw.Elapsed.TotalMilliseconds, 
    KeyValuePair.Create<string, object>("QueryType", "GetProducts"));

Grâce aux tags dans Grafana vous pouvez construire des graphes non seulement pour l'application entière, mais aussi pour des segments spécifiques.

5. Intégration avec Prometheus, Application Insights, Datadog, Grafana

Exporters et intégration

  • Prometheus — monitoring open-source populaire, quasi-standard pour le cloud et Kubernetes.
  • Application Insights — intégration cloud pour Azure.
  • Datadog, Grafana Cloud — pour des infrastructures pro.

Tous ces systèmes peuvent collecter des métriques depuis .NET via les exporters OpenTelemetry. Documentation sur les exporters OTel

Prometheus (étapes) :

  1. Ajouter le package NuGet : OpenTelemetry.Exporter.Prometheus.
  2. Ajouter .AddPrometheusExporter() lors de l'enregistrement des métriques.
  3. Dans Grafana configurer la datasource vers Prometheus et créer des dashboards.

Liens utiles :

6. Particularités, pièges et erreurs typiques

Une erreur fréquente — la sur-précision des tags. Si on met trop de valeurs uniques dans les tags (par ex. ID utilisateur/commande), le nombre de séries temporelles explose — ça surcharge le stockage des métriques et coûte cher (ce qu'on appelle la cardinality explosion). Gardez les tags gros-grain.

Les devs passent parfois à côté de System.Diagnostics.Metrics et réinventent la roue via des logs et timers. Au final le monitoring est moins intégré et plus dur à maintenir. Utilisez les outils standards et l'instrumentation automatique.

Autre pépin — les métriques sont collectées mais pas exportées. La configuration de l'exporter est obligatoire : ajoutez par exemple .AddPrometheusExporter() et vérifiez que l'endpoint /metrics est accessible pour le scraping.

Et enfin, confusion entre les types de métriques : on calcule le temps de réponse moyen via un Counter, alors qu'il faut utiliser un Histogram — sinon vous ne verrez pas les pics et la distribution. Les compteurs servent pour des quantités ; les histograms pour les temps/taille/distributions ; les gauges pour l'état courant.

Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION