Delen via


Een aangepaste logboekregistratieprovider implementeren in .NET

Er zijn veel logboekregistratieproviders beschikbaar voor algemene logboekregistratiebehoeften. Maar mogelijk moet u een aangepaste ILoggerProvider implementatie uitvoeren wanneer een van de beschikbare providers niet aan uw toepassingsbehoeften voldoet. In dit artikel leert u hoe u een aangepaste logboekregistratieprovider implementeert die kan worden gebruikt om logboeken in de console te kleuren.

Aanbeveling

De voorbeeldcode van de aangepaste logboekregistratieprovider is beschikbaar in de GitHub-opslagplaats van docs.

Voorbeeld van aangepaste logboekconfiguratie

De voorbeeldlogger maakt verschillende vermeldingen in de kleurenconsole per logboekniveau en gebeurtenis-id met behulp van het volgende configuratietype:

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
    };
}

Met de voorgaande code wordt de standaardkleur voor het Information niveau ingesteld op Green. De EventId is impliciet 0.

De aangepaste logboekregistratie maken

In het volgende codefragment ziet u de ILogger implementatie:

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();
        }
    }
}

Elk loggerexemplaar wordt geïnstantieerd door een categorienaam mee te geven, wat meestal het type is waarin de logger wordt gemaakt. De IsEnabled-methode controleert getCurrentConfig().LogLevelToColorMap.ContainsKey(logLevel) om te zien of het aangevraagde logboekniveau is ingeschakeld, dat wil zeggen in de woordenlijst van logboekniveaus van de configuratie.

Het is een goede gewoonte om ILogger.IsEnabled aan te roepen binnen ILogger.Log implementaties, omdat Log door elke consument kunnen worden aangeroepen en er geen garanties zijn dat deze eerder is gecontroleerd. De IsEnabled methode moet in de meeste implementaties zeer snel zijn.

if (!IsEnabled(logLevel))
{
    return;
}

De logger wordt geïnstantieerd met de name en een Func<ColorConsoleLoggerConfiguration> die de huidige configuratie retourneert.

Belangrijk

De ILogger.Log implementatie controleert of de config.EventId waarde is ingesteld. Wanneer config.EventId niet is ingesteld of overeenkomt met de exacte logEntry.EventId, wordt de logboekregistratie in kleur vastgelegd.

Aangepaste loggerprovider

Het ILoggerProvider-object is verantwoordelijk voor het maken van logger-instanties. Het is niet nodig om een loggerexemplaar per categorie te maken, maar voor sommige loggers, zoals NLog of log4net, is het zinvol. Met deze strategie kunt u verschillende uitvoerdoelen voor logboekregistratie per categorie kiezen, zoals in het volgende voorbeeld:

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();
    }
}

In de voorgaande code maakt CreateLogger(String) één exemplaar van de ColorConsoleLogger per categorienaam en slaat deze op in de ConcurrentDictionary<TKey,TValue>.

De ColorConsoleLoggerProvider klasse is ingericht met twee kenmerken:

[UnsupportedOSPlatform("browser")]
[ProviderAlias("ColorConsole")]
public sealed class ColorConsoleLoggerProvider : ILoggerProvider

De configuratie kan worden opgegeven met elke geldige configuratieprovider. Houd rekening met het volgende appsettings.json-bestand :

{
    "Logging": {
        "ColorConsole": {
            "LogLevelToColorMap": {
                "Information": "DarkGreen",
                "Warning": "Cyan",
                "Error": "Red"
            }
        }
    }
}

Het bestandappsettings.json geeft aan dat de kleur voor het Information logboekniveau is DarkGreen, waardoor de standaardwaarde die is ingesteld in het ColorConsoleLoggerConfiguration object wordt overschreven.

Gebruik en registratie van de aangepaste logger

Volgens de conventie worden services geregistreerd voor afhankelijkheidsinjectie als onderdeel van de opstartroutine van een toepassing. In dit voorbeeld wordt de logboekregistratieservice rechtstreeks vanuit het Program.cs-bestand geregistreerd.

Om de aangepaste loggingprovider en bijbehorende logger toe te voegen, voegt u een ILoggerProvider toe door de aangepaste extensiemethode AddColorConsoleLogger aan te roepen op de ILoggingBuilder van de IHostApplicationBuilder.Logging eigenschap.

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 value of "Cyan" from appsettings.json.
    configuration.LogLevelToColorMap[LogLevel.Warning]
        = ConsoleColor.DarkCyan;
    // Replace value of "Red" from appsettings.json.
    configuration.LogLevelToColorMap[LogLevel.Error]
        = ConsoleColor.DarkRed;
});

using IHost host = builder.Build();

ILogger<Program> 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();

Standaard worden extensiemethoden op ILoggingBuilder gebruikt om de aangepaste provider te registreren:

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;
    }
}

De ILoggingBuilder maakt een of meer ILogger instanties. De ILogger-instanties worden door het framework gebruikt om de informatie te loggen.

De instantiëringscode overschrijft de kleurwaarden uit het appsettings.json-bestand voor LogLevel.Warning en LogLevel.Error.

Wanneer u deze eenvoudige app uitvoert, wordt de kleuruitvoer weergegeven in het consolevenster, vergelijkbaar met de volgende afbeelding:

Voorbeelduitvoer van kleurenconsolelogger

Zie ook