Sdílet prostřednictvím


Implementace vlastního zprostředkovatele protokolování v .NET

Existuje mnoho poskytovatelů protokolování k dispozici pro běžné potřeby protokolování. Možná ale budete muset implementovat vlastní ILoggerProvider , pokud některý z dostupných poskytovatelů nevyhovuje potřebám vaší aplikace. V tomto článku se dozvíte, jak implementovat vlastního zprostředkovatele protokolování, který se dá použít k obarvení protokolů v konzole.

Návod

Ukázkový zdrojový kód vlastního zprostředkovatele protokolování je k dispozici v úložišti GitHubu docs.

Ukázková vlastní konfigurace loggeru

Ukázkový záznamník vytvoří různé barevné záznamy konzole podle úrovně logu a ID události pomocí následujícího typu konfigurace.

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

Předchozí kód nastaví výchozí barvu pro Information úroveň na Green. EventId je implicitně 0.

Vytvořte vlastní protokolovací nástroj

Následující fragment kódu ukazuje implementaci ILogger :

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

Každá instance loggeru se vytvoří předáním názvu kategorie, což je obvykle typ, kde je logger vytvořen. Metoda IsEnabled zkontroluje getCurrentConfig().LogLevelToColorMap.ContainsKey(logLevel) , jestli je povolená požadovaná úroveň protokolu (to znamená ve slovníku konfigurace úrovní protokolů).

Je dobrým zvykem volat ILogger.IsEnabled v rámci implementací ILogger.Log, protože Log může využívat jakýkoli spotřebitel a není zaručeno, že to bylo dříve zkontrolováno. Metoda IsEnabled by měla být ve většině implementací velmi rychlá.

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

Protokolovací nástroj je vytvořen s name a Func<ColorConsoleLoggerConfiguration>, která vrátí aktuální konfiguraci.

Důležité

Implementace ILogger.Log zkontroluje, jestli je nastavena hodnota config.EventId. Pokud config.EventId není nastaven nebo když odpovídá přesně logEntry.EventId, logger zaznamenává barevně.

Vlastní poskytovatel protokolu

Objekt ILoggerProvider zodpovídá za vytváření instancí loggeru. Není nutné vytvořit instanci protokolovacího nástroje pro každou kategorii, ale dává smysl pro některé protokolovací nástroje, jako je NLog nebo log4net. Tato strategie umožňuje zvolit různé cíle výstupu protokolování pro každou kategorii, jak je znázorněno v následujícím příkladu:

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

V předchozím kódu CreateLogger(String) vytvoří jednu instanci ColorConsoleLogger podle názvu kategorie a uloží ji do ConcurrentDictionary<TKey,TValue>.

Třída ColorConsoleLoggerProvider je zdobena dvěma atributy:

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

Konfiguraci lze zadat pomocí libovolného platného poskytovatele konfigurace . Zvažte následující appsettings.json soubor:

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

Soubor appsettings.json určuje, že barva Information úrovně protokolu je DarkGreen, která přepíše výchozí hodnotu nastavenou v objektu ColorConsoleLoggerConfiguration .

Použití a registrace vlastního protokolovacího nástroje

Podle konvence se služby registrují pro injektáž závislostí jako součást rutiny spouštění aplikace. V tomto příkladu je služba protokolování zaregistrována přímo ze souboru Program.cs .

Chcete-li přidat vlastního zprostředkovatele protokolování a odpovídající protokolovací nástroj, přidejte voláním ILoggerProvider vlastní rozšiřující metody , AddColorConsoleLoggerna ILoggingBuilder z IHostApplicationBuilder.Logging vlastnosti:

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

Podle konvence se metody rozšíření ILoggingBuilder používají k registraci vlastního poskytovatele:

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

ILoggingBuilder vytváří jednu nebo více instancí ILogger. ILogger instance jsou používány architekturou k protokolování informací.

Kód pro vytváření instancí přepíše hodnoty barev ze souboru appsettings.json pro LogLevel.Warning a LogLevel.Error.

Když spustíte tuto jednoduchou aplikaci, vykreslí výstup barev do okna konzoly podobně jako na následujícím obrázku:

Ukázkový výstup barevného konzolového loggeru

Viz také