.NET에서 사용자 지정 로깅 공급자 구현
일반적인 로깅 요구 사항에 사용할 수 있는 다양한 로깅 공급자가 있습니다. 사용 가능한 공급자 중 하나가 애플리케이션 요구 사항에 맞지 않는 경우 사용자 지정 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(
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
에 고유한 로거가 있습니다. 이 구현에서 각 로그 수준에는 로그에 명시적 구성 항목이 필요합니다.
Log
는 모든 소비자가 호출할 수 있고 이전에 확인되었다는 보장이 없으므로 ILogger.Log 구현 내에서 ILogger.IsEnabled를 호출하는 것이 좋습니다. IsEnabled
메서드는 대부분의 구현에서 매우 빠릅니다.
TState state,
Exception? exception,
로거는 콜백을 통해 현재 구성을 반환하는 name
및 Func<ColorConsoleLoggerConfiguration>
을 통해 인스턴스화됩니다. 이는 IOptionsMonitor<TOptions>.OnChange 콜백을 통해 모니터링되는 구성 값으로 업데이트를 처리합니다.
Important
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 로그 수준은 ColorConsoleLoggerConfiguration
개체에 설정된 기본값을 재정의하는 DarkGreen으로 설정됩니다.
사용자 지정 로거의 사용 및 등록
관례적으로 종속성 주입을 위한 서비스 등록은 애플리케이션 시작 루틴의 일부로 수행됩니다. 등록은 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