Partager via


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 Greenet 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) dans IsEnabled, de sorte que chaque logLevel 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 :

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 :

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 :

exemple de sortie couleur de l’enregistreur d’événements de console

Voir aussi