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 une ILoggerProvider personnalisée 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 dépôt GitHub Docs. Pour plus d’informations, consultez GitHub : .NET Docs - Console Custom Logging.
Exemple de configuration d’enregistreur d’événements personnalisé
L’exemple crée différentes entrées de console colorées selon le niveau de journalisation et l'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();
}
}
}
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 nécessite une entrée de configuration explicite pour journaliser.
Il est recommandé d’appeler ILogger.IsEnabled au sein des implémentations de ILogger.Log, car Log
peut être appelée par n’importe quel consommateur, et il n'y a aucune garantie que cela ait été vérifié précédemment. La méthode IsEnabled
doit être 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 exactement à logEntry.EventId
, l'enregistreur enregistre en couleur.
Fournisseur d’enregistreurs d’événements personnalisés
L’objet ILoggerProvider
est chargé de créer des 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 du ColorConsoleLogger
par nom de catégorie et la stocke dans le ConcurrentDictionary<TKey,TValue>
. En outre, l’interface IOptionsMonitor<TOptions> est nécessaire pour mettre à jour les modifications apportées à l’objet ColorConsoleLoggerConfiguration
sous-jacent.
Pour contrôler la configuration du 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. Tenez compte du 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();
Le ILoggingBuilder
crée une ou plusieurs instances ILogger
. Les instances ILogger
sont utilisées par l’infrastructure pour consigner les informations.
La configuration à partir du fichier appsettings.json remplace les valeurs suivantes :
Conventionnellement, les méthodes d’extension sur ILoggingBuilder
sont utilisées pour enregistrer 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 une sortie de couleur dans la fenêtre de console similaire à l’image suivante :