Implementieren eines benutzerdefinierten Protokollierungsanbieters in .NET
Viele Protokollierungsanbieter sind für allgemeine Protokollierungsanforderungen verfügbar. Möglicherweise müssen Sie eine benutzerdefinierte ILoggerProvider implementieren, wenn einer der verfügbaren Anbieter nicht ihren Anwendungsanforderungen entspricht. In diesem Artikel erfahren Sie, wie Sie einen benutzerdefinierten Protokollierungsanbieter implementieren, der zum Einfärben von Protokollen in der Konsole verwendet werden kann.
Tipp
Der beispielcode für den benutzerdefinierten Protokollierungsanbieter ist im Docs GitHub-Repositoryverfügbar. Weitere Informationen finden Sie unter GitHub: .NET-Dokumentation – Benutzerdefinierte Protokollierung in der Konsole.
Beispiel für eine benutzerdefinierte Loggerkonfiguration
Im Beispiel werden verschiedene Farbkonsoleneinträge pro Protokollebene und Ereignis-ID mithilfe des folgenden Konfigurationstyps erstellt:
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
};
}
Der vorangehende Code legt die Standardebene auf Information
, die Farbe auf Green
fest, und die EventId
ist implizit 0
.
Erstellen des benutzerdefinierten Loggers
Der Name der ILogger
-Implementierungskategorie ist normalerweise die Logquelle. Beispiel: Der Typ, in dem der Logger erstellt wird:
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();
}
}
}
Der vorangehende Code:
- Erstellt eine Loggerinstanz pro Kategoriename.
- Überprüft
_getCurrentConfig().LogLevelToColorMap.ContainsKey(logLevel)
inIsEnabled
, sodass jedeslogLevel
-Element über eine eindeutige Protokollierung verfügt. In dieser Implementierung erfordert jede Protokollebene einen expliziten Konfigurationseintrag zum Protokollieren.
Es empfiehlt sich, ILogger.IsEnabled innerhalb der ILogger.Log-Implementierungen aufzurufen, da Log
von jedem Nutzer aufgerufen werden kann, und es gibt keine Garantien, dass er zuvor überprüft wurde. Die IsEnabled
Methode sollte in den meisten Implementierungen sehr schnell sein.
TState state,
Exception? exception,
Der Logger wird mit dem name
und einem Func<ColorConsoleLoggerConfiguration>
instanziiert, der die aktuelle Konfiguration zurückgibt. Dadurch werden Aktualisierungen der Konfigurationswerte verarbeitet, die über den IOptionsMonitor<TOptions>.OnChange Rückruf überwacht werden.
Wichtig
Die ILogger.Log Implementierung überprüft, ob der config.EventId
Wert festgelegt ist. Wenn config.EventId
nicht festgelegt ist oder mit dem genauen logEntry.EventId
übereinstimmt, gibt der Logger die Protokolle in Farbe aus.
Benutzerdefinierter Loggeranbieter
Das ILoggerProvider
-Objekt ist für das Erstellen von Loggerinstanzen verantwortlich. Es ist nicht erforderlich, eine Loggerinstanz pro Kategorie zu erstellen, aber es ist sinnvoll für einige Logger, z. B. NLog oder Log4net. Mit dieser Strategie können Sie unterschiedliche Protokollierungsausgabeziele pro Kategorie auswählen, wie im folgenden Beispiel gezeigt:
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();
}
}
Im vorherigen Code erstellt CreateLogger eine einzelne Instanz des ColorConsoleLogger
pro Kategorienamen und speichert sie im ConcurrentDictionary<TKey,TValue>
. Darüber hinaus ist die IOptionsMonitor<TOptions> Schnittstelle erforderlich, um Änderungen an dem zugrunde liegenden ColorConsoleLoggerConfiguration
-Objekt zu aktualisieren.
Um die Konfiguration der ColorConsoleLogger
zu steuern, definieren Sie einen Alias beim Anbieter.
[UnsupportedOSPlatform("browser")]
[ProviderAlias("ColorConsole")]
public sealed class ColorConsoleLoggerProvider : ILoggerProvider
Die ColorConsoleLoggerProvider
-Klasse definiert zwei Klassenbereichsattribute:
- UnsupportedOSPlatformAttribute: Für den Typ
ColorConsoleLogger
gibt es keine Unterstützung in"browser"
. - ProviderAliasAttribute: Konfigurationsabschnitte können Optionen mithilfe des
"ColorConsole"
Schlüssels definieren.
Die Konfiguration kann mit jedem gültigen Konfigurationsanbieterfestgelegt werden. Betrachten Sie die folgende appsettings.json Datei:
{
"Logging": {
"ColorConsole": {
"LogLevelToColorMap": {
"Information": "DarkGreen",
"Warning": "Cyan",
"Error": "Red"
}
}
}
}
Dadurch werden die Protokollebenen mit den folgenden Werten konfiguriert:
- LogLevel.Information: ConsoleColor.DarkGreen
- LogLevel.Warning: ConsoleColor.Cyan
- LogLevel.Error: ConsoleColor.Red
Die Information Protokollebene wird auf DarkGreenfestgelegt, wodurch der im ColorConsoleLoggerConfiguration
-Objekt festgelegte Standardwert außer Kraft gesetzt wird.
Nutzung und Registrierung des benutzerdefinierten Loggers
Standardmäßig erfolgt das Registrieren von Diensten für die Abhängigkeitseinfügung im Rahmen der Startroutine einer Anwendung. Die Registrierung erfolgt in der Program
Klasse oder kann an eine Startup
Klasse delegiert werden. In diesem Beispiel registrieren Sie sich direkt über program.cs.
Fügen Sie ILoggerProvider mit ILoggingBuilder aus HostingHostBuilderExtensions.ConfigureLogging(IHostBuilder, Action<ILoggingBuilder>) hinzu, um die benutzerdefinierten Protokollierungsanbieter und die entsprechenden Protokollierungen hinzuzufügen:
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
erstellt mindestens eine ILogger
-Instanz. Die ILogger
Instanzen werden vom Framework verwendet, um die Informationen zu protokollieren.
Die Konfiguration aus der datei appsettings.json setzt die folgenden Werte außer Kraft:
Standardmäßig werden Erweiterungsmethoden für ILoggingBuilder
verwendet, um den benutzerdefinierten Anbieter zu registrieren:
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;
}
}
Wenn Sie diese einfache Anwendung ausführen, wird die Farbausgabe im Konsolenfenster ähnlich wie im folgenden Bild dargestellt.