Dela via


Implementera en anpassad loggningsprovider i .NET

Det finns många loggningsleverantörer tillgängliga för vanliga loggningsbehov. Du kan behöva implementera en anpassad ILoggerProvider när någon av de tillgängliga leverantörerna inte passar dina programbehov. I den här artikeln får du lära dig hur du implementerar en anpassad loggningsprovider som kan användas för att färglägga loggar i konsolen.

Tips

Exempelkällkoden för den anpassade loggningsprovidern finns i Docs GitHub-lagringsplatsen. Mer information finns i GitHub: .NET Docs – Console Custom Logging.

Exempel på anpassad loggningskonfiguration

Exemplet skapar olika färgkonsolposter per loggnivå och händelse-ID med hjälp av följande konfigurationstyp:

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

Föregående kod anger standardnivån till Information, färgen till Greenoch EventId är implicit 0.

Skapa den anpassade loggaren

Det ILogger implementeringskategorinamnet är vanligtvis loggningskällan. Till exempel typen där loggaren skapas:

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

Föregående kod:

  • Skapar en loggerinstans per kategorinamn.
  • Kontrollerar _getCurrentConfig().LogLevelToColorMap.ContainsKey(logLevel) i IsEnabled, så att varje logLevel har en unik loggare. I den här implementeringen kräver varje loggnivå en explicit konfigurationspost för att logga.

Det är en bra idé att anropa ILogger.IsEnabled inom ILogger.Log implementeringar eftersom Log kan anropas av alla konsumenter och det inte finns några garantier för att det har kontrollerats tidigare. Metoden IsEnabled bör vara mycket snabb i de flesta implementeringar.

TState state,
Exception? exception,

Loggern instansieras med name och en Func<ColorConsoleLoggerConfiguration>, som returnerar den nuvarande konfigurationen och hanterar uppdateringar av konfigurationsvärdena, vilka övervakas via IOptionsMonitor<TOptions>.OnChange-återanropet.

Viktig

Implementeringen ILogger.Log kontrollerar om värdet för config.EventId har angetts. När config.EventId inte har angetts eller när den exakt matchar logEntry.EventIdloggar loggarna i färg.

Anpassad loggningsleverantör

ILoggerProvider-objektet ansvarar för att skapa loggningsinstanser. Det är inte nödvändigt att skapa en loggningsinstans per kategori, men det är bra för vissa loggare, till exempel NLog eller log4net. Med den här strategin kan du välja olika utdatamål för loggning per kategori, som i följande exempel:

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

I föregående kod skapar CreateLogger en enda instans av ColorConsoleLogger per kategorinamn och lagrar den i ConcurrentDictionary<TKey,TValue>. Dessutom krävs IOptionsMonitor<TOptions>-gränssnittet för att uppdatera ändringar i det underliggande ColorConsoleLoggerConfiguration-objektet.

Om du vill styra konfigurationen av ColorConsoleLoggerdefinierar du ett alias på providern:

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

Klassen ColorConsoleLoggerProvider definierar två klassomfattade attribut.

Konfigurationen kan anges med valfri giltig konfigurationsleverantör. Överväg följande appsettings.json fil:

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

Detta konfigurerar loggnivåerna till följande värden:

Loggnivån Information är inställd på DarkGreen, vilket åsidosätter standardvärdet som anges i ColorConsoleLoggerConfiguration-objektet.

Användning och registrering av den anpassade loggaren

Enligt konventionen sker registrering av tjänster för beroendeinmatning som en del av startrutinen för ett program. Registreringen sker i klassen Program eller kan delegeras till en Startup-klass. I det här exemplet registrerar du dig direkt från Program.cs.

För att lägga till den anpassade loggningsprovidern och den motsvarande loggaren, lägg till en ILoggerProvider med ILoggingBuilder från 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 skapar en eller flera ILogger instanser. De ILogger instanserna används av ramverket för att logga informationen.

Konfigurationen från appsettings.json-filen åsidosätter följande värden:

Enligt konventionen används tilläggsmetoder på ILoggingBuilder för att registrera den anpassade providern:

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

Om du kör det här enkla programmet återges färgutdata till konsolfönstret som liknar följande bild:

färgkonsolloggerexempelutdata

Se även