Quand un client dit « c'est lent », il faut pouvoir répondre sans deviner. Les logs racontent ce qui s'est passé, les métriques mesurent (combien, à quelle vitesse), les traces suivent une requête d'un service à l'autre, comme un colis suivi à chaque étape de livraison.
Logs
Événements discrets, structurés, corrélés par TraceId. Pour comprendre un cas précis.
Métriques
Agrégats numériques : débit, latence p95/p99, taux d'erreur, GC, ThreadPool. Pour alerter.
Traces
Le parcours d'une requête entre services, découpé en spans. Pour localiser la lenteur.
OpenTelemetry, le standard Confirmé
.NET produit nativement des traces (ActivitySource) et des métriques (Meter) ; ASP.NET Core, HttpClient, EF Core et SqlClient sont déjà instrumentés. OpenTelemetry les collecte et les exporte en OTLP vers n'importe quel backend : Cloud Trace et Cloud Monitoring, Grafana (Tempo, Loki, Prometheus), Jaeger, Datadog…
builder.Services.AddOpenTelemetry()
.ConfigureResource(r => r.AddService("shop-api", serviceVersion: "1.8.2"))
.WithTracing(t => t
.AddAspNetCoreInstrumentation()
.AddHttpClientInstrumentation()
.AddSource("Shop.Orders") // vos propres ActivitySource
.AddOtlpExporter())
.WithMetrics(m => m
.AddAspNetCoreInstrumentation()
.AddHttpClientInstrumentation()
.AddRuntimeInstrumentation() // GC, ThreadPool, exceptions
.AddMeter("Shop.Orders")
.AddOtlpExporter());
builder.Logging.AddOpenTelemetry(l => { l.IncludeScopes = true; l.AddOtlpExporter(); });
// Span et métrique métier
private static readonly ActivitySource s_source = new("Shop.Orders");
private static readonly Counter<long> s_submitted =
new Meter("Shop.Orders").CreateCounter<long>("orders.submitted");
using var activity = s_source.StartActivity("SubmitOrder");
activity?.SetTag("order.id", orderId);
s_submitted.Add(1, new KeyValuePair<string, object?>("channel", "web"));
Logs structurés Junior
// ❌ Interpolation : une chaîne unique par appel, propriétés perdues, allocation même si le niveau est filtré
logger.LogInformation($"Commande {orderId} validée en {ms} ms");
// ✅ Message template : OrderId et ElapsedMs deviennent des champs filtrables
logger.LogInformation("Commande {OrderId} validée en {ElapsedMs} ms", orderId, ms);
// ✅✅ Source generator : zéro allocation, vérifié à la compilation
public static partial class Log
{
[LoggerMessage(Level = LogLevel.Information, Message = "Commande {OrderId} validée en {ElapsedMs} ms")]
public static partial void OrderSubmitted(this ILogger logger, Guid orderId, long elapsedMs);
}
Ne loggez jamais de secrets ni de données personnelles en clair (mots de passe, jetons, numéros de carte, e-mails selon votre politique RGPD). Le package Microsoft.Extensions.Compliance.Redaction masque les champs classifiés.
Outils de diagnostic Senior
| Outil | Usage |
|---|---|
dotnet-counters monitor -p <pid> | Compteurs en direct : CPU, GC, taille de la file du ThreadPool, requêtes/s |
dotnet-trace collect | Trace de performance (CPU, allocations), à ouvrir dans PerfView ou Visual Studio |
dotnet-dump collect / analyze | Dump mémoire : objets retenus, piles de threads (interblocages) |
dotnet-gcdump | Instantané léger du tas managé pour chasser une fuite |
| BenchmarkDotNet | Micro-benchmarks fiables avant d'optimiser |
| k6, NBomber | Tests de charge de l'API complète |
Alerter sur ce qui compte
Définissez des SLI (taux de requêtes réussies, latence p99) et des SLO (99,9 % de succès sur 30 jours). Alertez sur la consommation du budget d'erreur plutôt que sur un pic de CPU isolé : une alerte doit appeler une action.
- Cardinalité explosive : un identifiant utilisateur en tag de métrique crée une série par utilisateur. Les identifiants vont dans les traces et logs, pas dans les métriques.
- Échantillonnage absent : 100 % des traces à fort trafic coûte cher ; échantillonner (par exemple 10 %) en gardant toutes les erreurs.
- Health check qui ment : un
/healthqui renvoie toujours 200 sans rien vérifier.
À retenir
- OpenTelemetry pour les trois signaux, export OTLP, corrélation par TraceId.
- Message templates ou
[LoggerMessage], jamais d'interpolation dans les logs. dotnet-countersd'abord,dotnet-traceoudotnet-dumpensuite.