在 .NET 中實作自訂記錄提供者
有許多記錄提供者可用來滿足常見的記錄需求。 當其中一種提供者不符合您應用程式的需求時,您可能需要實作一個自訂 ILoggerProvider。 在本文中,您將了解如何實作自訂記錄提供者以在主控台中進行彩色記錄。
提示
Docs Github 存放庫提供自訂記錄提供者的原始程式碼範例。 如需詳細資訊,請參閱 GitHub:.NET Docs - 主控台自訂記錄 (英文)。
自訂記錄器設定範例
此範例會使用下列設定類型,為每個記錄層級和事件識別碼建立不同的彩色主控台項目:
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)
,讓每個都有logLevel
都有獨一無二的記錄器。 在此實作中,每個記錄層級都需要明確的設定項目來進行記錄。
建議您在 ILogger.Log 實作中呼叫 ILogger.IsEnabled,因為任何取用者都可以呼叫 Log
,而且不能保證它先前有經過檢查。 在大部分的實作中,方法 IsEnabled
應該都非常快速。
TState state,
Exception? exception,
記錄器會透過 name
和 Func<ColorConsoleLoggerConfiguration>
具現化並傳回目前的設定,這會處理透過 IOptionsMonitor<TOptions>.OnChange 回呼監控的設定值更新。
重要
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 會為每個類別名稱建立一個 ColorConsoleLogger
執行個體,並將它儲存在 ConcurrentDictionary<TKey,TValue>
中。 此外,要更新基礎 ColorConsoleLoggerConfiguration
物件的變更,就必須使用 IOptionsMonitor<TOptions> 介面。
若要控制 ColorConsoleLogger
的設定,您可以在其提供者上定義一個別名:
[UnsupportedOSPlatform("browser")]
[ProviderAlias("ColorConsole")]
public sealed class ColorConsoleLoggerProvider : ILoggerProvider
類別 ColorConsoleLoggerProvider
會定義兩個以類別為範圍的屬性:
- UnsupportedOSPlatformAttribute:
"browser"
不支援ColorConsoleLogger
類型。 - ProviderAliasAttribute:設定區段可以使用
"ColorConsole"
索引鍵來定義選項。
您可以使用任何有效的設定提供者來指定設定。 請考慮下列 appsettings.json 檔案:
{
"Logging": {
"ColorConsole": {
"LogLevelToColorMap": {
"Information": "DarkGreen",
"Warning": "Cyan",
"Error": "Red"
}
}
}
}
這會將記錄層級設為下列值:
- LogLevel.Information: ConsoleColor.DarkGreen
- LogLevel.Warning: ConsoleColor.Cyan
- LogLevel.Error: ConsoleColor.Red
記錄層級 Information 已設為 DarkGreen,並且覆寫了 ColorConsoleLoggerConfiguration
物件中設定的預設值。
自訂記錄器的使用方式和註冊
依照慣例,相依性插入的註冊服務是應用程式啟動常式的一部分。 註冊會以 Program
類別發生,或可以委派給 Startup
類別。 在此範例中,您將直接從 Program.cs 進行註冊。
若要新增自訂記錄提供者和對應的記錄器,請從 HostingHostBuilderExtensions.ConfigureLogging(IHostBuilder, Action<ILoggingBuilder>) 新增一個具有 ILoggingBuilder 的 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 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
會建立一或多個 ILogger
執行個體。 架構會使用 ILogger
執行個體來記錄資訊。
appsettings.json 檔案中的設定會覆寫下列值:
依照慣例,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;
}
}
執行這個簡單的應用程式可以將彩色輸出轉譯至主控台視窗,如下圖所示: