Delen via


Een aangepaste logboekregistratieprovider implementeren in .NET

Er zijn veel logboekregistratieproviders beschikbaar voor algemene logboekregistratiebehoeften. Mogelijk moet u een aangepaste ILoggerProvider implementeren 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.

Tip

De voorbeeldbroncode van de aangepaste logboekregistratieprovider is beschikbaar in de Docs GitHub-opslagplaats. Zie GitHub: .NET Docs - Aangepaste logboekregistratie van de consolevoor meer informatie.

Voorbeeld van aangepaste logboekconfiguratie

In het voorbeeld worden verschillende vermeldingen in de kleurenconsole per logboekniveau en gebeurtenis-id gemaakt 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 het standaardniveau ingesteld op Information, de kleur op Greenen wordt de EventId impliciet 0.

De aangepaste logboekregistratie maken

De naam van de ILogger implementatiecategorie is doorgaans de logbron. Bijvoorbeeld het type waar de logger wordt gemaakt:

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

De voorgaande code:

  • Hiermee maakt u een logboekregistratie-exemplaar per categorienaam.
  • Controleert _getCurrentConfig().LogLevelToColorMap.ContainsKey(logLevel) in IsEnabled, zodat elke logLevel een unieke logger heeft. In deze implementatie vereist elk logboekniveau een expliciete configuratievermelding voor het logboek.

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.

TState state,
Exception? exception,

De logger wordt geïnstantieerd met de name en een Func<ColorConsoleLoggerConfiguration>, die de huidige configuratie retourneert. Hiermee worden updates van de configuratiewaarden verwerkt die worden bewaakt via de IOptionsMonitor<TOptions>.OnChange callback.

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 één exemplaar van de ColorConsoleLogger per categorienaam en slaat deze op in de ConcurrentDictionary<TKey,TValue>. Daarnaast is de IOptionsMonitor<TOptions>-interface vereist om wijzigingen in het onderliggende ColorConsoleLoggerConfiguration-object bij te werken.

Als u de configuratie van de ColorConsoleLoggerwilt beheren, definieert u een alias op de provider:

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

De ColorConsoleLoggerProvider klasse definieert twee kenmerken met een klassebereik:

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

Hiermee configureert u de logboekniveaus op de volgende waarden:

Het Information logboekniveau is ingesteld op DarkGreen, waardoor de standaardwaarde die is ingesteld in het ColorConsoleLoggerConfiguration-object wordt overschreven.

Gebruik en registratie van de aangepaste logger

Volgens de conventie vindt het registreren van services voor afhankelijkheidsinjectie plaats als onderdeel van de opstartroutine van een toepassing. De registratie vindt plaats in de Program klasse of kan worden gedelegeerd aan een Startup-klasse. In dit voorbeeld registreert u zich rechtstreeks vanuit de Program.cs.

Om de aangepaste logprovider en bijbehorende logger toe te voegen, voeg een ILoggerProvider toe met ILoggingBuilder uit 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();

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

De configuratie van het bestand appsettings.json overschrijft de volgende waarden:

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

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

Voorbeelduitvoer van kleurenconsolelogger

Zie ook