Implémenter un fournisseur de journalisation personnalisé dans .NET
Il existe de nombreux fournisseurs de journalisation disponibles pour les besoins courants de journalisation. Vous devrez peut-être implémenter un fournisseur personnalisé ILoggerProvider lorsque l’un des fournisseurs disponibles ne répond pas aux besoins de votre application. Dans cet article, vous allez apprendre à implémenter un fournisseur de journalisation personnalisé qui peut être utilisé pour coloriser les journaux dans la console.
Conseil
L’exemple de code source du fournisseur de journalisation personnalisé est disponible dans le référentiel Github Docs. Pour plus d’informations, consultez GitHub : .NET Docs, Journalisation personnalisée console.
Exemple de configuration d’enregistreur d’événements personnalisé
L’exemple crée différentes entrées de console de couleur par niveau de journal et identifiant d’événement à l’aide du type de configuration suivant :
using Microsoft.Extensions.Logging;
public sealed class ColorConsoleLoggerConfiguration
{
public int EventId { get; set; }
public Dictionary<LogLevel, ConsoleColor> LogLevelToColorMap { get; set; } = new()
{
[LogLevel.Information] = ConsoleColor.Green
};
}
Le code précédent définit le niveau par défaut sur Information
, la couleur sur Green
et l’EventId
est implicitement 0
.
Créer l’enregistreur d’événements personnalisé
Le nom de catégorie d’implémentation ILogger
est généralement la source de journalisation. Par exemple, le type où l’enregistreur d’événements est créé :
using Microsoft.Extensions.Logging;
public sealed class ColorConsoleLogger(
string name,
Func<ColorConsoleLoggerConfiguration> getCurrentConfig) : ILogger
{
public IDisposable? BeginScope<TState>(TState state) where TState : notnull => default!;
public bool IsEnabled(LogLevel logLevel) =>
getCurrentConfig().LogLevelToColorMap.ContainsKey(logLevel);
public void Log<TState>(
LogLevel logLevel,
EventId eventId,
TState state,
Exception? exception,
Func<TState, Exception?, string> formatter)
{
if (!IsEnabled(logLevel))
{
return;
}
ColorConsoleLoggerConfiguration config = getCurrentConfig();
if (config.EventId == 0 || config.EventId == eventId.Id)
{
ConsoleColor originalColor = Console.ForegroundColor;
Console.ForegroundColor = config.LogLevelToColorMap[logLevel];
Console.WriteLine($"[{eventId.Id,2}: {logLevel,-12}]");
Console.ForegroundColor = originalColor;
Console.Write($" {name} - ");
Console.ForegroundColor = config.LogLevelToColorMap[logLevel];
Console.Write($"{formatter(state, exception)}");
Console.ForegroundColor = originalColor;
Console.WriteLine();
}
}
}
Le code précédent :
- Crée une instance d’enregistreur d’événements par nom de catégorie.
- Vérifie
_getCurrentConfig().LogLevelToColorMap.ContainsKey(logLevel)
dansIsEnabled
, de sorte que chaquelogLevel
ait un enregistreur d’événements unique. Dans cette implémentation, chaque niveau de journal a besoin d’une entrée de configuration explicite à journaliser.
Il est recommandé d’appeler ILogger.IsEnabled dans les implémentations ILogger.Log, car Log
peut être appelé par n’importe quel consommateur, et aucune garantie ne prouve qu’il a été vérifié précédemment. La méthode IsEnabled
est très rapide dans la plupart des implémentations.
TState state,
Exception? exception,
L’enregistreur d’événements est instancié avec name
et Func<ColorConsoleLoggerConfiguration>
, qui retourne la configuration actuelle. Il gère les mises à jour des valeurs de configuration, comme prévu par le biais du rappel IOptionsMonitor<TOptions>.OnChange.
Important
L’implémentation ILogger.Log vérifie si la valeur config.EventId
est définie. Quand config.EventId
n’est pas défini ou lorsqu’il correspond à logEntry.EventId
, l’enregistreur d'événements journalise en couleur.
Fournisseur d’enregistreurs d’événements personnalisés
L’objet ILoggerProvider
est responsable de la création d’instances d’enregistreur d’événements. Il n’est pas nécessaire de créer une instance d’enregistreur d’événements par catégorie, mais il est logique pour certains enregistreurs d’événements, tels que NLog ou log4net. Cette stratégie vous permet de choisir différentes cibles de sortie de journalisation par catégorie, comme dans l’exemple suivant :
using System.Collections.Concurrent;
using System.Runtime.Versioning;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
[UnsupportedOSPlatform("browser")]
[ProviderAlias("ColorConsole")]
public sealed class ColorConsoleLoggerProvider : ILoggerProvider
{
private readonly IDisposable? _onChangeToken;
private ColorConsoleLoggerConfiguration _currentConfig;
private readonly ConcurrentDictionary<string, ColorConsoleLogger> _loggers =
new(StringComparer.OrdinalIgnoreCase);
public ColorConsoleLoggerProvider(
IOptionsMonitor<ColorConsoleLoggerConfiguration> config)
{
_currentConfig = config.CurrentValue;
_onChangeToken = config.OnChange(updatedConfig => _currentConfig = updatedConfig);
}
public ILogger CreateLogger(string categoryName) =>
_loggers.GetOrAdd(categoryName, name => new ColorConsoleLogger(name, GetCurrentConfig));
private ColorConsoleLoggerConfiguration GetCurrentConfig() => _currentConfig;
public void Dispose()
{
_loggers.Clear();
_onChangeToken?.Dispose();
}
}
Dans le code précédent, CreateLogger crée une instance unique de ColorConsoleLogger
par nom de catégorie et la stocke dans ConcurrentDictionary<TKey,TValue>
. En outre, l’interface IOptionsMonitor<TOptions> est nécessaire pour mettre à jour les modifications apportées à l’objet sous-jacent ColorConsoleLoggerConfiguration
.
Pour contrôler la configuration de ColorConsoleLogger
, vous définissez un alias sur son fournisseur :
[UnsupportedOSPlatform("browser")]
[ProviderAlias("ColorConsole")]
public sealed class ColorConsoleLoggerProvider : ILoggerProvider
La classe ColorConsoleLoggerProvider
définit deux attributs d’étendue de classe :
- UnsupportedOSPlatformAttribute: le type
ColorConsoleLogger
n’est pas pris en charge dans"browser"
. - ProviderAliasAttribute: les sections de configuration peuvent définir des options à l’aide de la clé
"ColorConsole"
.
La configuration peut être spécifiée avec n’importe quel fournisseur de configuration valide. Considérez le fichier appsettings.json suivant :
{
"Logging": {
"ColorConsole": {
"LogLevelToColorMap": {
"Information": "DarkGreen",
"Warning": "Cyan",
"Error": "Red"
}
}
}
}
Cela configure les niveaux de journal sur les valeurs suivantes :
- LogLevel.Information: ConsoleColor.DarkGreen
- LogLevel.Warning: ConsoleColor.Cyan
- LogLevel.Error: ConsoleColor.Red
Le niveau de journal Information est défini sur DarkGreen, qui remplace la valeur par défaut définie dans l’objet ColorConsoleLoggerConfiguration
.
Utilisation et inscription de l’enregistreur d’événements personnalisé
Par convention, l’inscription de services pour l’injection de dépendances se produit dans le cadre de la routine de démarrage d’une application. L’inscription se produit dans la classe Program
ou peut être déléguée à une classe Startup
. Dans cet exemple, vous allez vous inscrire directement à partir du fichier Program.cs.
Pour ajouter le fournisseur de journalisation personnalisé et l’enregistreur d’événements correspondants, ajoutez ILoggerProvider avec ILoggingBuilder partir de HostingHostBuilderExtensions.ConfigureLogging(IHostBuilder, Action<ILoggingBuilder>) :
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Logging.ClearProviders();
builder.Logging.AddColorConsoleLogger(configuration =>
{
// Replace warning value from appsettings.json of "Cyan"
configuration.LogLevelToColorMap[LogLevel.Warning] = ConsoleColor.DarkCyan;
// Replace warning value from appsettings.json of "Red"
configuration.LogLevelToColorMap[LogLevel.Error] = ConsoleColor.DarkRed;
});
using IHost host = builder.Build();
var logger = host.Services.GetRequiredService<ILogger<Program>>();
logger.LogDebug(1, "Does this line get hit?"); // Not logged
logger.LogInformation(3, "Nothing to see here."); // Logs in ConsoleColor.DarkGreen
logger.LogWarning(5, "Warning... that was odd."); // Logs in ConsoleColor.DarkCyan
logger.LogError(7, "Oops, there was an error."); // Logs in ConsoleColor.DarkRed
logger.LogTrace(5, "== 120."); // Not logged
await host.RunAsync();
ILoggingBuilder
crée une ou plusieurs instances ILogger
. Les instances ILogger
sont utilisées par l’infrastructure pour enregistrer les informations.
La configuration du fichier appsettings.json remplace les valeurs suivantes :
Par convention, les méthodes d’extension sur ILoggingBuilder
sont utilisées pour inscrire le fournisseur personnalisé :
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Configuration;
public static class ColorConsoleLoggerExtensions
{
public static ILoggingBuilder AddColorConsoleLogger(
this ILoggingBuilder builder)
{
builder.AddConfiguration();
builder.Services.TryAddEnumerable(
ServiceDescriptor.Singleton<ILoggerProvider, ColorConsoleLoggerProvider>());
LoggerProviderOptions.RegisterProviderOptions
<ColorConsoleLoggerConfiguration, ColorConsoleLoggerProvider>(builder.Services);
return builder;
}
public static ILoggingBuilder AddColorConsoleLogger(
this ILoggingBuilder builder,
Action<ColorConsoleLoggerConfiguration> configure)
{
builder.AddColorConsoleLogger();
builder.Services.Configure(configure);
return builder;
}
}
L’exécution de cette application simple affiche la sortie de couleur dans la fenêtre de console similaire à l’image suivante :