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 Green
och 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)
iIsEnabled
, så att varjelogLevel
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.EventId
loggar 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 ColorConsoleLogger
definierar du ett alias på providern:
[UnsupportedOSPlatform("browser")]
[ProviderAlias("ColorConsole")]
public sealed class ColorConsoleLoggerProvider : ILoggerProvider
Klassen ColorConsoleLoggerProvider
definierar två klassomfattade attribut.
-
UnsupportedOSPlatformAttribute: Typen
ColorConsoleLogger
stöds inte i"browser"
. -
ProviderAliasAttribute: Konfigurationsavsnitt kan definiera alternativ med hjälp av
"ColorConsole"
-nyckeln.
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:
- LogLevel.Information: ConsoleColor.DarkGreen
- LogLevel.Warning: ConsoleColor.Cyan
- LogLevel.Error: ConsoleColor.Red
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: