有很多
日志记录提供程序
可用于常见日志记录需求。 如果某个可用的提供程序不满足你的应用程序需要,则你可能需要实现自定义的
ILoggerProvider
。 在本文中,你将学习如何实现可用于在控制台中为日志着色的自定义日志记录提供程序。
Docs Github 存储库中提供了自定义日志记录提供程序示例源代码。 有关详细信息,请参阅
GitHub:.NET Docs - 控制台自定义日志记录
。
示例自定义记录器配置
此示例会使用以下配置类型为每个日志级别和事件 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 : ILogger
private readonly string _name;
private readonly Func<ColorConsoleLoggerConfiguration> _getCurrentConfig;
public ColorConsoleLogger(
string name,
Func<ColorConsoleLoggerConfiguration> getCurrentConfig) =>
(_name, _getCurrentConfig) = (name, getCurrentConfig);
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
方法应该非常快。
public bool IsEnabled(LogLevel logLevel) =>
_getCurrentConfig().LogLevelToColorMap.ContainsKey(logLevel);
记录器使用
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
:
"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;
using IHost host = Host.CreateDefaultBuilder(args)
.ConfigureLogging(builder =>
builder.ClearProviders()
.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;
.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 文件中的配置会替代以下值:
LogLevel.Warning
:
ConsoleColor.DarkCyan
LogLevel.Error
:
ConsoleColor.DarkRed
按照约定,
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 中的高性能日志记录