다음을 통해 공유


.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,

로거는 현재 구성을 반환하는 nameFunc<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 클래스는 두 클래스 범위 특성을 정의합니다.

구성은 유효한 구성 공급자사용하여 지정할 수 있습니다. 다음 appsettings.json 파일을 고려합니다.

{
    "Logging": {
        "ColorConsole": {
            "LogLevelToColorMap": {
                "Information": "DarkGreen",
                "Warning": "Cyan",
                "Error": "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;
    }
}

이 간단한 애플리케이션을 실행하면 다음 이미지와 비슷한 색 출력이 콘솔 창에 렌더링됩니다.

컬러 콘솔 로거 샘플 출력

참고 항목