有許多 記錄提供者 可用於常見的記錄需求。 但當現有供應商不符合你的應用需求時,可能需要實施自訂 ILoggerProvider 方案。 在本文中,你將學習如何實作一個自訂的日誌服務提供者,該服務可以用來在主控台中為日誌上色。
小提示
自訂日誌提供者範例原始碼可在 文件的 GitHub 倉庫中找到。
範例自定義記錄器組態
範例記錄器會依照日誌層級和事件 ID 建立不同的色彩主控台條目,使用以下設定類型:
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
};
}
前述程式碼將關卡的預設顏色 Information 設定為 Green。 該 EventId 隱含為 0。
建立自訂記錄器
以下程式碼片段展示了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();
}
}
}
每個記錄器實例都是透過傳遞該記錄器的類別名稱來建立,這個類別名稱通常是指建立該記錄器的類型。 該IsEnabled方法會檢查getCurrentConfig().LogLevelToColorMap.ContainsKey(logLevel)所請求的日誌層級是否啟用(即在組態的日誌層級對應表中)。
最好是在 ILogger.IsEnabled 實作內呼叫 ILogger.Log,因為任何使用者都可以呼叫 Log,且不保證先前已進行檢查。
IsEnabled 方法在大部分的實作中應該非常快速。
if (!IsEnabled(logLevel))
{
return;
}
記錄器以 name 和一個 Func<ColorConsoleLoggerConfiguration> 實例化,後者回傳當前配置。
這很重要
ILogger.Log 實作會檢查是否已設定 config.EventId 值。 未設定 config.EventId 或符合確切 logEntry.EventId時,記錄器會以色彩記錄。
自訂記錄器提供者
ILoggerProvider 物件負責建立記錄器實例。 不需要為每個類別建立記錄器實例,但對於某些記錄器而言,例如 NLog 或 log4net 是合理的。 此策略可讓您為每個類別選擇不同的記錄輸出目標,如下列範例所示:
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();
}
}
在上述程式代碼中,CreateLogger(String) 會為每個類別名稱建立 ColorConsoleLogger 的單一實例,並將它儲存在 ConcurrentDictionary<TKey,TValue>中。
該 ColorConsoleLoggerProvider 職業擁有兩項屬性:
[UnsupportedOSPlatform("browser")]
[ProviderAlias("ColorConsole")]
public sealed class ColorConsoleLoggerProvider : ILoggerProvider
-
UnsupportedOSPlatformAttribute:
ColorConsoleLogger類型在 中不支援"browser"。 -
ProviderAliasAttribute:組態區段可以使用
"ColorConsole"鍵來定義選項。
可以藉由任何有效的 組態提供者來指定組態,。 以下列 appsettings.json 檔案為例:
{
"Logging": {
"ColorConsole": {
"LogLevelToColorMap": {
"Information": "DarkGreen",
"Warning": "Cyan",
"Error": "Red"
}
}
}
}
appsettings.json 檔案指定對數層級的顏色Information為 DarkGreen,這會覆蓋物件中ColorConsoleLoggerConfiguration預設的值。
自訂記錄器的使用方式和註冊
依慣例,服務會在應用程式啟動例程中註冊以注入相依性。 在此範例中,日誌服務是直接從 Program.cs 檔案註冊的。
若要新增自訂日誌提供者及對應的日誌工具,請在IHostApplicationBuilder.Logging屬性的ILoggingBuilder上,呼叫自訂擴充方法AddColorConsoleLogger以加入ILoggerProvider。
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();
依照慣例,ILoggingBuilder 上的擴充方法可用來註冊自定義提供者:
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 會建立一或多個 ILogger 實例。 架構會使用 ILogger 實例來記錄資訊。
實例化程式碼會覆蓋 appsettings.json 檔案中 和 LogLevel.WarningLogLevel.Error的顏色值。
當你執行這個簡單的應用程式時,它會將顏色輸出輸出到主控台視窗,類似以下圖片: