L’enregistrement (logging) est une partie essentielle et précieuse du développement logiciel. Il devient une nécessité dans toute bibliothèque ou application. L’enregistrement peut aider à identifier des problèmes à n’importe quelle étape du développement logiciel, mais surtout lorsque le débogage ne peut pas être utilisé de manière habituelle.
Par exemple, lorsque vous déployez votre application en production, sans aucun moyen de visualiser son fonctionnement, vous pouvez simplement lire les informations enregistrées pour vérifier si tout se déroule correctement. Enfin, l’enregistrement peut être utile à des stades ultérieurs, après la sortie du produit. Si quelque chose se passe mal après une longue période de fonctionnement stable, vous pouvez simplement consulter les informations d’enregistrement, et dans la plupart des cas, cela suffira pour comprendre ce qui n’a pas fonctionné.
Cet article s’adresse aux développeurs .NET qui souhaitent implémenter l’enregistrement dans leurs projets et qui ne connaissent pas les différents frameworks d’enregistrement tiers et les fonctionnalités qu’ils peuvent offrir. Il décrit les étapes principales de l’implémentation de l’enregistrement, de l’installation et de la configuration du framework à l’écriture des premiers journaux d’application. Dans cet article, vous découvrirez l’enregistrement de données structurées dans différents frameworks, ainsi que les avantages et les inconvénients de chacun. Les exemples de cet article ont été rédigés en utilisant le framework .NET Core.
Qu’est-ce que l’enregistrement structuré ?
Pour tirer pleinement parti de l’enregistrement, vous devez implémenter cette fonctionnalité correctement. Plus vous fournissez d’informations utiles et nécessaires via l’enregistrement, plus il vous sera facile de répondre à la question « Qu’est-ce qui a mal tourné ? ». Cela ne signifie pas qu’il faut tout enregistrer, il faut simplement identifier les cas où l’enregistrement est nécessaire. Mais enregistrer uniquement les messages d’exception peut être inutile. Par exemple, si vous obtenez dans vos journaux quelque chose comme « Référence d’objet nulle » sans aucun contexte, nom de paramètre, ni même nom de fonction où l’exception a été levée. Vous devez fournir suffisamment d’informations pour faciliter le processus de recherche de bogues. Pour y parvenir simplement, vous pouvez utiliser des frameworks d’enregistrement .Net spéciaux qui peuvent offrir de nombreuses fonctionnalités comme l’enregistrement structuré.
L’enregistrement simple signifie que tous les enregistrements sont stockés sous forme de chaînes de caractères. Or, de nombreux problèmes ne peuvent pas être clairement décrits en quelques mots. Dans ce cas, nous devons utiliser l’enregistrement structuré : stocker des objets entiers dans les journaux. Par exemple, le corps de la requête, le modèle utilisateur, la requête de transaction, etc. Cela peut aider à reproduire une erreur et à comprendre ce qui s’est mal passé.
De plus, l’enregistrement structuré peut offrir des fonctionnalités de tri et de recherche dans les fichiers journaux. Par exemple, vous pouvez fournir le modèle de l’utilisateur pour les requêtes échouées, puis simplement rechercher par ClientId dans les journaux. Avec l’aide des frameworks d’enregistrement, vous pouvez passer n’importe quel objet souhaité dans vos journaux en toute simplicité.
Par exemple, si nous utilisons un enregistrement simple, nos journaux ressembleront à ceci :
2019-02-04T12:23:34Z INFO Completed 200 OK in 79ms (Views: 78.8ms | ActiveRecord: 0.0ms)
Ce ne sera pas très utile en cas d’erreur, nous pouvons donc améliorer ce journal grâce à l’enregistrement structuré. Dans ce cas, nous pouvons obtenir quelque chose comme ceci :
{
"dt": "2020-04-07T12:23:34Z",
"level": "info",
"message": "Completed 200 OK in 79ms (Views: 78.8ms | ActiveRecord: 0.0ms)",
"context": {
"host": "34.225.155.83",
"user_id": 5,
"path": "/welcome",
"method": "GET"
},
"http_response_sent": {
"status": 200,
"duration_ms": 79.0,
"view_ms": 78.8,
"active_record_ms": 0.0
}
}
Cela semble mieux et nous avons obtenu des avantages :
- Données bien structurées dans un format d’encodage officiel (JSON).
- Aucune règle d’analyse spéciale.
- Travail avec les données de manière simple (recherche, filtrage, tri, visualisation lisible par l’homme, etc.).
Mais avant de commencer avec les journaux structurés, nous devons implémenter l’enregistrement de manière générale.
API d’enregistrement intégrée
Pour commencer à travailler avec l’API d’enregistrement, vous avez besoin d’un fournisseur qui affiche ou stocke les journaux. Vous pouvez choisir le fournisseur Console pour voir les journaux dans la console de votre application, ou le fournisseur Azure Application Insights pour les stocker dans Azure. Soit dit en passant, vous pouvez utiliser plusieurs fournisseurs pour stocker les journaux dans différents endroits. Si vous utilisez une application avec Generic Host, vous devez simplement appeler la méthode AddConsole (ou tout autre nom de fournisseur). Essayons avec le modèle de projet Web API par défaut.
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureLogging(configureLogging => {
configureLogging.ClearProviders();
configureLogging.AddConsole();
})
.ConfigureWebHostDefaults(webBuilder => {
webBuilder.UseStartup();
});
La méthode ClearProviders est utilisée pour effacer tous les fournisseurs déjà ajoutés (par défaut). Vous pouvez ainsi remplacer les valeurs par défaut par les fournisseurs de votre choix.
Après avoir ajouté les fournisseurs d’enregistrement, vous pouvez créer des journaux. Cela peut se faire en utilisant l’objet ILogger<>, qui peut être obtenu par injection de dépendances. Ensuite, vous devez créer un logger avec une catégorie spécifique (chaîne de caractères), qui peut être le nom d’un contrôleur ou d’une classe :
public class WeatherForecastController : ControllerBase {
private readonly ILogger _logger;
public WeatherForecastController(ILogger logger) {
_logger = logger;
}
Vous êtes alors prêt à écrire des journaux. Cela peut se faire avec des méthodes telles que LogInformation, LogError, LogWarning, etc. Par exemple :
public IEnumerable Get() {
_logger.LogInformation("Method 'Get' called at {0}", DateTime.UtcNow);
var rng = new Random();
return Enumerable.Range(1, 5).Select(index => new WeatherForecast {
Date = DateTime.Now.AddDays(index),
TemperatureC = rng.Next(-20, 55),
Summary = Summaries[rng.Next(Summaries.Length)]
})
.ToArray();
}
}
Ensuite, si vous avez ajouté Console comme fournisseur, après chaque appel de cette méthode, vous pouvez voir dans la console de sortie quelque chose comme :
Method `Get` called 04/07/2020 09:58:06
Pour écrire des journaux, vous pouvez utiliser l’un des niveaux de journalisation suivants, fournis par .NET Core :
- Trace = 0. Généralement utilisé uniquement pour le développement, désactivé par défaut pour éviter l’envoi de données sensibles en production.
- Debug = 1. Toutes les informations de débogage (par exemple, la valeur d’un paramètre à une étape d’exécution du code), peuvent être activées en production pour le dépannage.
- Information = 2. Informations générales utilisées pour fournir des messages sur l’étape ou l’état actuel du système.
- Warning = 3. Utilisé pour signaler les événements inattendus qui ne provoquent pas de crash ni ne bloquent l’exécution de l’application.
- Error = 4. Utilisé pour les erreurs et exceptions non gérées qui peuvent indiquer un échec dans l’opération en cours.
- Critical = 5. Utilisé pour fournir des informations sur les erreurs qui nécessitent une attention immédiate. Par exemple, manque de mémoire disque, etc.
Frameworks d’enregistrement .NET
L’utilisation d’un framework tiers est très similaire à l’utilisation des fournisseurs intégrés. Il suffit d’ajouter un package NuGet à votre projet, puis d’appeler une méthode d’extension ILoggerFactory que votre framework d’enregistrement fournit. Ces frameworks peuvent vous offrir plus de possibilités et de fonctionnalités pour améliorer votre processus d’enregistrement, effectuer un enregistrement sémantique et améliorer la visualisation des journaux créés.
Dans cet article, nous examinerons trois frameworks d’enregistrement différents pour .NET : NLog, Serilog et Log4Net.
Framework d’enregistrement NLog

NLog est une plateforme d’enregistrement gratuite pour les plateformes .NET. NLog prend en charge la modification de la configuration d’enregistrement à la volée, l’enregistrement structuré, et peut facilement écrire vers plusieurs cibles. Les principaux avantages de l’utilisation de NLog sont : sa facilité d’utilisation, d’extension, de configuration et ses hautes performances.
Pour commencer à utiliser le framework NLog, vous devez installer la dernière version des packages NLog et NLog.Web.AspNetCore via le gestionnaire de packages NuGet.
Ensuite, vous devez créer le fichier nlog.config à la racine du projet. Ce fichier décrit les cibles vers lesquelles écrire les journaux et quelques règles supplémentaires pour commencer l’enregistrement.
<!--?xml version="1.0" encoding="utf-8" ?-->
<!-- enable asp.net core layout renderers -->
<!-- the targets to write to -->
<!-- write logs to file -->
<!-- another file log, only own logs. Uses some ASP.NET core renderers -->
<!-- rules to map from logger name to target -->
<!--All logs, including from Microsoft-->
<!--Skip non-critical Microsoft logs and so log only own logs-->
<!-- BlackHole without writeTo -->
L’étape suivante consiste à activer la copie du dossier bin pour nlog.config. Cela peut se faire de la manière suivante :
Dans l’Explorateur de solutions, ouvrez les propriétés du fichier nlog.config, puis définissez le paramètre « Copier dans le répertoire de sortie » sur « Copier si plus récent ».

Ensuite, vous devez mettre à jour le fichier Program.cs pour initialiser NLog.
public class Program {
public static void Main(string[] args) {
var logger = NLog.Web.NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger();
try {
logger.Debug("init main");
CreateHostBuilder(args).Build().Run();
}
catch (Exception exception) {
//NLog: catch setup errors
logger.Error(exception, "Stopped program because of exception");
throw;
}
finally {
// Ensure to flush and stop internal timers/threads before application-exit (Avoid segmentation fault on Linux)
NLog.LogManager.Shutdown();
}
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureLogging(configureLogging => {
configureLogging.ClearProviders();
configureLogging.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace);
})
.ConfigureWebHostDefaults(webBuilder => {
webBuilder.UseStartup();
})
.UseNLog(); // NLog: Setup NLog for Dependency injection
}
L’étape suivante consiste à configurer appsettings.json. Vous devez supprimer « Default » ou y mettre les bonnes valeurs. Sinon, cela annulera tout appel à SetMinimumLevel. Vous pouvez configurer l’enregistrement de cette manière :
{
"Logging": {
"IncludeScopes": false,
"LogLevel": {
"Default": "Trace",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*"
}
Si vous avez différents environnements et que vous utilisez différents fichiers de configuration, n’oubliez pas de spécifier ces paramètres dans chacun d’eux.
Maintenant, une fois que vous avez terminé toutes les étapes ci-dessus, vous pouvez essayer d’écrire des journaux. Par exemple, vous pouvez écrire des journaux dans votre contrôleur comme ceci :
public class WeatherForecastController : ControllerBase {
private readonly ILogger _logger;
public WeatherForecastController(ILogger logger) {
_logger = logger;
_logger.LogDebug(1, "NLog injected into WeatherForecastController");
}
private static readonly string[] Summaries = new[] {
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
[HttpGet]
public IEnumerable Get() {
_logger.LogInformation("Method 'Get' called at {0}", DateTime.UtcNow);
var rng = new Random();
return Enumerable.Range(1, 5).Select(index => new WeatherForecast {
Date = DateTime.Now.AddDays(index),
TemperatureC = rng.Next(-20, 55),
Summary = Summaries[rng.Next(Summaries.Length)]
})
.ToArray();
}
}
Comme vous pouvez le constater, l’utilisation de NLog est très similaire à l’enregistrement .NET Core par défaut. Vous pouvez maintenant vérifier vos journaux à l’endroit que vous avez configuré dans le fichier nlog.config. Ils ressembleront à ceci :
2020-04-07 14:31:58.4400||DEBUG|LoggingSample.Program|init main
2020-04-07 14:31:59.1861||INFO|Microsoft.Hosting.Lifetime|Application started. Press Ctrl+C to shut down.
2020-04-07 14:31:59.1861||INFO|Microsoft.Hosting.Lifetime|Hosting environment: Development
2020-04-07 14:31:59.1979||INFO|Microsoft.Hosting.Lifetime|Content root path: C:UsersAdminsourcereposLoggingSampleLoggingSample
2020-04-07 14:31:59.2970||INFO|LoggingSample.Controllers.WeatherForecastController|Method 'Get' called at 07-Apr-20 11:31:59
Pour utiliser l’enregistrement structuré dans NLog, vous pouvez simplement contrôler le formatage en faisant précéder `@`. Par exemple :
var order = new Order {
OrderId = 2,
Status = OrderStatus.Processing
};
logger.Info("Order updated: {@value1}", order);
Résultat de la sortie :
Order updated: {"OrderId":2, "Status":"Processing"}
Si nous utilisons cette instruction sans le symbole `@`, comme ceci :
logger.Info("Order updated: {value1}", order);
Comme vous pouvez le voir, l’utilisation de l’enregistrement structuré dans le framework NLog est vraiment simple. Un seul symbole permet de donner plus de contexte à vos journaux, ce qui peut aider dans le processus de gestion des erreurs.
En résumé, le framework NLog est très similaire à l’enregistrement par défaut, et il est très facile à configurer et à utiliser. D’ailleurs, il n’y a qu’une chose à savoir avant d’utiliser ce framework : vous n’obtiendrez aucun indice si quelque chose ne fonctionne pas avec NLog. Par exemple, si vous oubliez votre fichier de configuration, NLog ne fonctionnera pas. Vous n’en serez pas averti. Cela a été fait pour éviter que des applications ne tombent en panne à cause de l’enregistrement. Mais cela peut être une mauvaise surprise si quelque chose se passe mal, et vous découvrirez que les journaux sont vides en raison d’une configuration incorrecte du fichier.
Framework d’enregistrement Serilog
Serilog est une autre bibliothèque qui permet l’enregistrement vers la console, des fichiers ou ailleurs. Elle possède une API claire et est facile à configurer. Elle est conçue en pensant aux données d’événements structurées puissantes.
Pour commencer à travailler avec Serilog, vous devez installer deux packages via NuGet : Serilog et Serilog.Sinks.Console. Pour créer un logger, il vous suffit d’écrire le code ci-dessous :
var logger = new LoggerConfiguration()
.WriteTo.Console()
.CreateLogger();
Après cela, vous pouvez facilement utiliser le logger de la même manière qu’un logger intégré :
log.Information("Hello, Serilog!");
Vous pouvez également changer le fournisseur pour n’importe lequel d’autre en utilisant la méthode d’extension WriteTo. Par exemple, pour utiliser la sortie fichier, vous pouvez essayer le code ci-dessous :
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
.WriteTo.File("logsmyapp.txt", rollingInterval: RollingInterval.Day)
.CreateLogger();
Log.Information(“Hello, world !”);
Serilog prend en charge l’enregistrement structuré. Si vous avez besoin d’enregistrer un objet, vous pouvez simplement utiliser l’instruction suivante :
var position = new { Latitude = 25, Longitude = 134 };
var elapsedMs = 34;
log.Information("Processed {@Position} in {Elapsed:000} ms.", position, elapsedMs);
Cet opérateur « @ » indique à Serilog de sérialiser l’objet et de le convertir en utilisant la méthode ToString.
Une autre fonctionnalité intéressante de Serilog est l’enricher. Il s’agit d’une partie de code qui s’exécute à chaque requête de journalisation et fournit des informations supplémentaires à la requête. Avec l’aide de l’enricher, vous pouvez fournir plus d’informations sans aucune action spéciale à chaque requête. Vous pouvez simplement ajouter des propriétés supplémentaires à votre requête. Cela permet de rendre les traces de pile plus compréhensibles.
Si vous consultez les journaux, vous obtiendrez quelque chose comme ceci :
[15:46:03 INF] Hello, world!
[15:46:03 INF] Processed { Latitude: 25, Longitude: 134 } in 034 ms.
[15:46:03 DBG] Dividing 10 by 0
[15:46:03 ERR] Something went wrong
Comme vous pouvez le voir, l’enregistrement structuré a fourni le modèle d’objet complet au format JSON dans les journaux. Il active donc toutes les fonctionnalités de l’enregistrement structuré sans aucun problème, et il est très facile à implémenter dans votre application.
En résumé, Serilog est un outil relativement facile à utiliser. La prise en charge de l’enregistrement structuré est très appréciable, et les journaux peuvent être envoyés vers un grand nombre de destinations.
Framework d’enregistrement Apache log4net

Log4net est une bibliothèque qui permet d’afficher la sortie du logger vers n’importe quelle cible de sortie. Log4net offre la possibilité d’activer ou de désactiver l’enregistrement à l’exécution sans modifier le code de l’application. Les principaux avantages sont la vitesse et la flexibilité.
Pour commencer à travailler avec log4net, vous devez l’installer via NuGet. Ensuite, nous devons créer un fichier de configuration. Il est au format XML et devrait contenir quelque chose comme ceci :
<!-- Pattern to output the caller's file name and line number -->
Après cela, nous pouvons commencer à travailler avec log4net. Les journaux structurés dans log4net peuvent être créés sans syntaxe spéciale, simplement en passant un objet comme paramètre. Le code ci-dessous montre un exemple d’utilisation de log4net pour créer des journaux simples et structurés :
class Program {
private static readonly ILog log = LogManager.GetLogger(typeof(Program));
static void Main(string[] args) {
var logRepository = LogManager.GetRepository(Assembly.GetEntryAssembly());
XmlConfigurator.Configure(logRepository, new FileInfo("log4net.config"));
log.Debug("Starting up");
log.Debug(new { color = "red", num = 1 });
log.Debug("Shutting down");
Console.ReadLine();
}
}
Si nous exécutons cette application puis vérifions la sortie, nous pouvons voir :
2018-08-18 18:57:37,278 DEBUG 1 LoggingDemo.Log4Net.Program - Starting up
2018-08-18 18:57:37,298 DEBUG 1 LoggingDemo.Log4Net.Program - { color = red, int1 = 1 }
2018-08-18 18:57:37,298 DEBUG 1 LoggingDemo.Log4Net.Program - Shutting down
En résumé pour log4net, je dois faire attention à quelques points importants. Il n’est pas bien documenté du tout, et il peut être difficile de commencer à travailler avec. Le fichier de configuration par défaut n’est pas le bon choix. Vous devez le configurer vous-même. Donc, si vous avez besoin d’un démarrage rapide et d’une documentation appropriée, peut-être devriez-vous essayer autre chose.
Conclusion
Comparons quelques étapes de base pour implémenter l’enregistrement structuré et les fonctionnalités qui peuvent être fournies.
| log4net | NLog | Serilog | |
| Documentation | Dispose de documentation générale et d’exemples | Bien documenté et dispose de nombreux exemples | Bien documenté et dispose de nombreux exemples et tutoriels |
| Compatibilité .NET | .NET Framework 2.0 ou supérieur .NET Core 1.0 ou supérieur |
.NET Frameworks 3.5 – 4.8 .NET Core 1.0 ou supérieur |
.NET Framework 4.5 ou supérieur .NET Core 1.0 ou supérieur |
| Passer l’objet entier aux journaux | Il suffit de passer un objet en paramètre | Marquer un objet avec `@` | Marquer un objet avec `@` |
| Configuration | Besoin de personnaliser le fichier de configuration pour obtenir une meilleure visualisation des journaux | Aucune configuration spéciale requise pour l’enregistrement structuré | Aucune configuration spéciale requise pour l’enregistrement structuré |
| Complexité de l’implémentation | Similaire à l’API d’enregistrement par défaut, mais nécessite de personnaliser le fichier de configuration | Similaire à l’API d’enregistrement par défaut, facile à implémenter, mais aucun indice si l’implémentation a échoué et qu’elle ne fonctionne pas | Similaire à l’API d’enregistrement par défaut, facile à implémenter |
Comme vous pouvez le constater, ces trois frameworks d’enregistrement .NET sont similaires, et il n’est pas très difficile de passer à l’un d’entre eux, car ils ont des instructions similaires et peuvent être facilement installés et utilisés. De plus, nous pouvons utiliser n’importe lequel de ces frameworks pour implémenter l’enregistrement structuré dans votre application. Tous offrent des fonctionnalités similaires.
Cependant, si nous devons prendre une décision et en choisir un seul, je recommanderais d’essayer Serilog en raison de son API moderne, de sa facilité de configuration, de maintenance et de son support intégré simple pour l’enregistrement structuré. De plus, il est très bien documenté et facile à utiliser, dans l’ensemble. Cependant, comme ils sont tous assez similaires, vous pouvez essayer de les utiliser tous sans aucune difficulté et prendre votre propre décision.
Découvrez comment nous avons adapté une application de recommandation musicale Facebook pour son lancement sur le marché américain en utilisant des frameworks .NET
