1. Introduction
En programmation, la journalisation n'est pas juste "afficher quelque chose dans la console". La journalisation, c'est votre boîte noire, votre traceur GPS et votre indicateur tout-en-un. Sans logs, une grosse application devient une boîte noire-mystère : "pourquoi le service a planté ?", "pourquoi l'utilisateur n'a pas reçu l'email ?", "est-ce que quelqu'un a lancé ce module ces 3 derniers mois ?" — à toutes ces questions on peut souvent répondre uniquement si les logs sont conservés et accessibles.
Pourquoi la journalisation est-elle utile en pratique ?
Recherche et diagnostic des erreurs
Si le programme a planté — les logs diront où et pourquoi. Si il n'a pas planté, mais se comporte étrangement — les logs indiqueront les étapes qui ont mené à cela.
Monitoring de l'état
Avec les logs on peut savoir si le système fonctionne maintenant, s'il y a beaucoup de requêtes vers le serveur, s'il y a des erreurs, qui fait quoi.
Sécurité
Journaliser les tentatives d'accès non autorisé, l'activité suspecte, les erreurs d'authentification.
Audit
Qui a fait quoi et quand. Si un admin malveillant a quitté et supprimé des données, les logs permettent de tout reconstituer (ou au moins de comprendre ce qu'il a fait).
Support en développement et exploitation
Les logs ne sont pas seulement pour le développeur, mais aussi pour le testeur, l'opérateur, l'admin. Dans six mois vous vous direz : 'Merci d'avoir ajouté des logs !'
De Console.WriteLine au logging industriel
La réaction initiale d'un débutant : "Et si on se contente de Console.WriteLine ?". Pour des petits programmes d'apprentissage ça suffit souvent. Mais quand l'application tourne sur un serveur, fonctionne en parallèle, ou est utilisée par des dizaines ou centaines d'utilisateurs, la console n'aide plus. Il faut :
- Séparer l'information importante des messages de debug.
- Envoyer les logs non seulement vers la console, mais aussi vers des fichiers, des bases de données, des systèmes centralisés.
- Changer le niveau de détail des logs (minimum — seulement les erreurs, maximum — tout).
- Compléter automatiquement les entrées par la date, l'heure et des métadonnées.
- Configurer de façon flexible.
- Et surtout — ne pas modifier le code juste pour rediriger les logs ailleurs.
C'est là que commence l'ère des "vrais" loggers.
2. Bases d'un système de logging moderne en .NET
Dans l'écosystème .NET il existe un framework standard, puissant et flexible pour la journalisation — Microsoft.Extensions.Logging. C'est une partie de la "nouvelle vague" de bibliothèques .NET apparues avec ASP.NET Core, mais on l'utilise partout maintenant : serveur, desktop, et même mobile.
Pourquoi ce framework est-il bien ?
- Abstraction — il ne vous lie pas à une implémentation spécifique (le logger peut écrire dans un fichier, la console, le cloud, ou tout en même temps).
- Support des niveaux de logging (Trace, Debug, Information, Warning, Error, Critical).
- Intégration dans le DI container et usage dans toutes les applications .NET modernes.
- Écosystème riche d'extensions : support du structured logging, formatters avancés et intégrations.
Concepts et classes principales
Voyons les objets clés dont nous aurons besoin pour travailler avec Microsoft.Extensions.Logging :
| Classe/Interface | But |
|---|---|
|
Interface pour la journalisation, typée par classe |
|
Interface générique de logger |
|
Factory pour créer des instances de loggers |
|
Permet de configurer le logging dans l'application |
|
Énumération des niveaux de logs (Trace, Debug, Information, ...) |
Niveaux de logging
Diviser les messages par niveau d'importance permet de filtrer le "bruit" et de trouver ce dont on a besoin :
| Niveau (LogLevel) | Quand l'utiliser ? |
|---|---|
|
Debug très verbeux, "bruit", données temporaires |
|
Information de debug principale |
|
Messages événementiels clés pour le fonctionnement normal |
|
Avertissements sur des problèmes potentiels, mais le système continue |
|
Erreurs demandant de l'attention, mais l'application est encore vivante |
|
Pannes critiques menaçant tout le système |
3. Pratique : ajouter la journalisation dans notre application
Ne écrivons pas du code abstrait, continuons plutôt à développer notre application démo. Imaginons qu'on ait déjà une classe Calculator simple, que l'on va étendre au fil du cours.
Exemple : un calculator de base
public class Calculator
{
public int Add(int a, int b)
{
return a + b;
}
// Autres méthodes...
}
Intégrons maintenant la journalisation. Pour ça on a besoin de l'interface ILogger<Calculator>, qu'on recevra de l'extérieur (par exemple via Dependency Injection, DI).
using Microsoft.Extensions.Logging;
public class Calculator
{
private readonly ILogger<Calculator> _logger;
public Calculator(ILogger<Calculator> logger)
{
_logger = logger;
}
public int Add(int a, int b)
{
int result = a + b;
_logger.LogInformation("Exécution de l'addition : {A} + {B} = {Result}", a, b, result);
return result;
}
}
Fait intéressant :
Au lieu de concaténer des chaînes, les loggers supportent des templates et des paramètres nommés ({A}, {B}, {Result}), ce qui permet d'avoir des logs structurés et faciles à analyser automatiquement et à rechercher.
4. Comment créer et configurer un logger dans une application console
1. Ajouter les paquets NuGet
Dans votre projet il vous faudra :
- Microsoft.Extensions.Logging
- Microsoft.Extensions.Logging.Console (si vous voulez écrire dans la console)
- (optionnel) d'autres providers si nécessaire
2. Configurer le logger
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
// On crée le DI-container
var serviceProvider = new ServiceCollection()
.AddLogging(builder => {
builder.AddConsole(); // Sortie vers la console
builder.SetMinimumLevel(LogLevel.Debug); // Niveau minimum de logs
})
.BuildServiceProvider();
// On récupère une instance du logger du type voulu
var logger = serviceProvider.GetRequiredService<ILogger<Calculator>>();
var calculator = new Calculator(logger);
calculator.Add(5, 3); // Un message ira dans les logs
Erreur typique des débutants
"Pourquoi le log n'apparaît pas dans la console ?" — vérifiez si le provider nécessaire est ajouté (.AddConsole()) et si le niveau minimum est correctement défini (SetMinimumLevel). Si le niveau est plus élevé, les messages peuvent tout simplement être "filtrés" !
5. Astuces utiles
Logger les erreurs et les situations non standard
Supposons qu'on veuille logger une division par zéro. Ajoutons la méthode correspondante :
public int Divide(int a, int b)
{
if (b == 0)
{
_logger.LogError("Tentative de division par zéro ! a={A}", a);
throw new DivideByZeroException();
}
int result = a / b;
_logger.LogInformation("Exécution de la division : {A} / {B} = {Result}", a, b, result);
return result;
}
Pourquoi c'est utile ?
Dans une vraie application, quand quelque chose va mal, les logs de niveau Error attirent généralement une attention particulière : ils sont automatiquement envoyés aux admins, mis en évidence dans le monitoring et utilisés pour des alerts/notifications.
Utiliser des catégories et des balises (scopes)
Le logger en .NET supporte les fameux scopes — ce sont des métadonnées additionnelles qui sont automatiquement ajoutées à tous les logs pendant un certain bloc de code. Par exemple, si vous traitez une requête web ou une session utilisateur, vous pouvez ajouter son identifiant dans un scope.
using (_logger.BeginScope("UserId: {UserId}", 42))
{
_logger.LogInformation("Début du traitement des données de l'utilisateur");
// ...
}
Tous les messages à l'intérieur du bloc recevront la balise additionnelle UserId: 42, ce qui aidera ensuite à retrouver les logs par utilisateur ou par opération.
Exemple : niveaux de logging en action
_logger.LogTrace("Ceci est Trace — presque personne ne verra");
_logger.LogDebug("Ceci est Debug — pour les développeurs");
_logger.LogInformation("Ceci est Information — pour les événements normaux");
_logger.LogWarning("Ceci est Warning — avertissement d'un problème possible");
_logger.LogError("Ceci est Error — une erreur nécessitant de l'attention");
_logger.LogCritical("Ceci est Critical — le système brûle, il faut un pompier !");
Si vous avez configuré SetMinimumLevel(LogLevel.Information), vous verrez seulement les messages des niveaux Information, Warning, Error, Critical.
Astuce :
Gardez les logs Trace et Debug pour une diagnostic détaillée en développement, et en production active laissez souvent seulement Information et au-dessus pour ne pas gonfler la taille des logs et ne pas perdre l'important dans le "bruit".
Schéma visuel : architecture du logging moderne
graph TD
A[Code de l'application] --ILogger<YourClass>--> B[Microsoft.Extensions.Logging]
B --> C1[Console Provider]
B --> C2[File Provider]
B --> C3[Cloud/Database Provider]
C1 -.-> D1[Logs dans la console]
C2 -.-> D2[Logs dans le fichier]
C3 -.-> D3[Logs dans le système de monitoring]
subgraph Providers
C1
C2
C3
end
6. Fonctionnalités additionnelles et extensions
Structured logging :
Les valeurs des paramètres peuvent être conservées non seulement dans la chaîne, mais aussi en tant que paires clé-valeur, ce qui permet la recherche et l'agrégation par ces paramètres (par exemple via Seq, ELK/ElasticSearch ou Application Insights).
Providers de logging :
On peut ajouter des dizaines de providers différents : fichier, Windows EventLog, Azure, etc.
Configurer le logging via appsettings.json
Dans ASP.NET Core, les logs sont configurables via un fichier de configuration, sans recompiler l'application.
Exemple de configuration du niveau minimum via le config (appsettings.json) :
{
"Logging": {
"LogLevel": {
"Default": "Information",
"MyApp.Calculator": "Debug",
"Microsoft": "Warning"
}
}
}
7. Erreurs typiques en utilisant Microsoft.Extensions.Logging
Erreur n°1 : Mauvais choix du niveau de logging.
Utiliser LogInformation pour des erreurs au lieu de LogError ou LogCritical complique la recherche des problèmes en production.
Erreur n°2 : Ignorer le structured logging.
Concaténer des chaînes au lieu d'utiliser des templates avec des placeholders ({Parameter}) prive des avantages du structured logging, comme la recherche par paramètres.
Erreur n°3 : Mauvaise configuration des niveaux de logging.
Si le niveau minimum est réglé trop haut (par exemple Warning au lieu de Debug), des messages importants peuvent être filtrés.
Erreur n°4 : Logging excessif ou insuffisant.
Trop de détails (par exemple Trace en production) crée du "bruit", tandis que l'absence de logs rend le diagnostic difficile.
GO TO FULL VERSION