在 .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>
中。 此外,需要 IOptionsMonitor<TOptions> 介面,才能更新基礎 ColorConsoleLoggerConfiguration
對象的變更。
若要控制 ColorConsoleLogger
的組態,您可以在其提供者上定義別名:
[UnsupportedOSPlatform("browser")]
[ProviderAlias("ColorConsole")]
public sealed class ColorConsoleLoggerProvider : ILoggerProvider
ColorConsoleLoggerProvider
類別會定義兩個類別範圍屬性:
-
UnsupportedOSPlatformAttribute:
ColorConsoleLogger
類型在"browser"
中不支援 。 -
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;
}
}
執行這個簡單的應用程式會將色彩輸出轉譯至主控台視窗,如下圖所示:
另請參閱
- 在 .NET 中 記錄
- .NET 中的記錄提供者
- .NET 中的相依性注入
- .NET 中的高效能記錄