다음을 통해 공유


콘솔 로그 서식 지정

.NET 5에서는 네임스페이스의 Microsoft.Extensions.Logging.Console 콘솔 로그에 사용자 지정 서식 지정 지원이 추가되었습니다. 세 가지 미리 정의된 서식 지정 옵션을 사용할 수 있습니다SimpleSystemdJson.

중요합니다

이전에는 ConsoleLoggerFormat 열거형을 사용하여 원하는 로그 형식을 선택할 수 있었습니다. 즉, 사람이 읽을 수 있는 Default 형식 또는 단일 줄 형식이라고도 알려진 Systemd 형식입니다. 그러나 이러한 항목은 사용자 지정할 수 없으며 이제 더 이상 사용되지 않습니다.

이 문서에서는 콘솔 로그 포맷터에 대해 알아봅니다. 샘플 소스 코드는 다음 방법을 보여 줍니다.

  • 새 포맷터 등록
  • 사용할 등록된 포맷터 선택
    • 코드 또는 구성을 통해
  • 사용자 지정 포맷터 구현

팁 (조언)

모든 로깅 예제 소스 코드는 샘플 브라우저에서 다운로드할 수 있습니다. 자세한 내용은 코드 샘플 찾아보기: .NET의 로깅을 참조하세요.

포맷터 등록

Console 로깅 공급자에는 미리 정의된 여러 포맷터가 있으며 사용자 고유의 사용자 지정 포맷터를 작성하는 기능을 노출합니다. 사용 가능한 포맷터를 등록하려면 해당 Add{Type}Console 확장 메서드를 사용합니다.

사용 가능한 형식 형식을 등록하는 방법
ConsoleFormatterNames.Json ConsoleLoggerExtensions.AddJsonConsole
ConsoleFormatterNames.Simple ConsoleLoggerExtensions.AddSimpleConsole
ConsoleFormatterNames.Systemd ConsoleLoggerExtensions.AddSystemdConsole

단순

Simple 콘솔 포맷터를 사용하려면 AddSimpleConsole로 등록하십시오.

using Microsoft.Extensions.Logging;

using ILoggerFactory loggerFactory =
    LoggerFactory.Create(builder =>
        builder.AddSimpleConsole(options =>
        {
            options.IncludeScopes = true;
            options.SingleLine = true;
            options.TimestampFormat = "HH:mm:ss ";
        }));

ILogger<Program> logger = loggerFactory.CreateLogger<Program>();
using (logger.BeginScope("[scope is enabled]"))
{
    logger.LogInformation("Hello World!");
    logger.LogInformation("Logs contain timestamp and log level.");
    logger.LogInformation("Each log message is fit in a single line.");
}

이전 샘플 소스 코드에서 ConsoleFormatterNames.Simple 포맷터가 등록되었습니다. 로그 메시지에 시간 및 로그 수준과 같은 정보를 포함할 수 있는 기능뿐만 아니라, 메시지에 ANSI 색상을 삽입하고 들여쓰기를 제공하는 기능을 지원합니다.

이 샘플 앱을 실행하면 아래와 같이 로그 메시지의 형식이 지정됩니다.

간단한 포맷터로 작성된 콘솔 로그 예제입니다.

Systemd

ConsoleFormatterNames.Systemd 콘솔 로거:

  • "Syslog" 로그 수준 형식 및 심각도 사용
  • 색을 사용하여 메시지의 서식을 지정하지 않음
  • 항상 메시지를 한 줄로 기록합니다.

이는 일반적으로 Systemd 콘솔 로깅을 사용하는 컨테이너에 유용합니다. .NET 5의 Simple 콘솔 로거는 한 줄로 로그하는 컴팩트 버전을 제공하며, 이전 샘플과 같이 색상을 비활성화할 수 있도록 합니다.

using Microsoft.Extensions.Logging;

using ILoggerFactory loggerFactory =
    LoggerFactory.Create(builder =>
        builder.AddSystemdConsole(options =>
        {
            options.IncludeScopes = true;
            options.TimestampFormat = "HH:mm:ss ";
        }));

ILogger<Program> logger = loggerFactory.CreateLogger<Program>();
using (logger.BeginScope("[scope is enabled]"))
{
    logger.LogInformation("Hello World!");
    logger.LogInformation("Logs contain timestamp and log level.");
    logger.LogInformation("Systemd console logs never provide color options.");
    logger.LogInformation("Systemd console logs always appear in a single line.");
}

이 예제에서는 다음 로그 메시지와 유사한 출력을 생성합니다.

Systemd 포맷터로 작성된 콘솔 로그 예제입니다.

Json

JSON 형식 Json 으로 로그를 작성하기 위해 콘솔 포맷터가 사용됩니다. 샘플 소스 코드는 ASP.NET Core 앱이 등록하는 방법을 보여줍니다. 템플릿을 webapp 사용하여 dotnet new 명령을 사용하여 새 ASP.NET Core 앱을 만듭니다.

dotnet new webapp -o Console.ExampleFormatters.Json

템플릿 코드를 사용하여 앱을 실행할 때 아래의 기본 로그 형식을 가져옵니다.

info: Console.ExampleFormatters.Json.Startup[0]
      Hello .NET friends!
info: Microsoft.Hosting.Lifetime[14]
      Now listening on: https://localhost:5001
info: Microsoft.Hosting.Lifetime[14]
      Now listening on: http://localhost:5000
info: Microsoft.Hosting.Lifetime[0]
      Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
      Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]
      Content root path: .\snippets\logging\console-formatter-json

기본적으로 Simple 콘솔 로그 포맷터는 기본 구성으로 선택됩니다. AddJsonConsole 호출 하여 이를 변경합니다.

using System.Text.Json;

HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);

builder.Logging.AddJsonConsole(options =>
{
    options.IncludeScopes = false;
    options.TimestampFormat = "HH:mm:ss ";
    options.JsonWriterOptions = new JsonWriterOptions
    {
        Indented = true
    };
});

using IHost host = builder.Build();

var logger =
    host.Services
        .GetRequiredService<ILoggerFactory>()
        .CreateLogger<Program>();

logger.LogInformation("Hello .NET friends!");

await host.RunAsync();

또는 appsettings.json 파일에 있는 것과 같은 로깅 구성을 사용하여 이를 구성할 수도 있습니다.

{
    "Logging": {
        "LogLevel": {
            "Default": "Information",
            "Microsoft": "Warning",
            "Microsoft.Hosting.Lifetime": "Information"
        },
        "Console": {
            "LogLevel": {
                "Default": "Information",
                "Microsoft": "Warning",
                "Microsoft.Hosting.Lifetime": "Information"
            },
            "FormatterName": "json",
            "FormatterOptions": {
                "SingleLine": true,
                "IncludeScopes": true,
                "TimestampFormat": "HH:mm:ss ",
                "UseUtcTimestamp": true,
                "JsonWriterOptions": {
                    "Indented": true
                }
            }
        }
    },
    "AllowedHosts": "*"
}

위의 변경 내용으로 앱을 다시 실행하면 로그 메시지의 형식이 JSON으로 지정됩니다.

{
  "Timestamp": "02:28:19 ",
  "EventId": 0,
  "LogLevel": "Information",
  "Category": "Console.ExampleFormatters.Json.Startup",
  "Message": "Hello .NET friends!",
  "State": {
    "Message": "Hello .NET friends!",
    "{OriginalFormat}": "Hello .NET friends!"
  }
}
{
  "Timestamp": "02:28:21 ",
  "EventId": 14,
  "LogLevel": "Information",
  "Category": "Microsoft.Hosting.Lifetime",
  "Message": "Now listening on: https://localhost:5001",
  "State": {
    "Message": "Now listening on: https://localhost:5001",
    "address": "https://localhost:5001",
    "{OriginalFormat}": "Now listening on: {address}"
  }
}
{
  "Timestamp": "02:28:21 ",
  "EventId": 14,
  "LogLevel": "Information",
  "Category": "Microsoft.Hosting.Lifetime",
  "Message": "Now listening on: http://localhost:5000",
  "State": {
    "Message": "Now listening on: http://localhost:5000",
    "address": "http://localhost:5000",
    "{OriginalFormat}": "Now listening on: {address}"
  }
}
{
  "Timestamp": "02:28:21 ",
  "EventId": 0,
  "LogLevel": "Information",
  "Category": "Microsoft.Hosting.Lifetime",
  "Message": "Application started. Press Ctrl\u002BC to shut down.",
  "State": {
    "Message": "Application started. Press Ctrl\u002BC to shut down.",
    "{OriginalFormat}": "Application started. Press Ctrl\u002BC to shut down."
  }
}
{
  "Timestamp": "02:28:21 ",
  "EventId": 0,
  "LogLevel": "Information",
  "Category": "Microsoft.Hosting.Lifetime",
  "Message": "Hosting environment: Development",
  "State": {
    "Message": "Hosting environment: Development",
    "envName": "Development",
    "{OriginalFormat}": "Hosting environment: {envName}"
  }
}
{
  "Timestamp": "02:28:21 ",
  "EventId": 0,
  "LogLevel": "Information",
  "Category": "Microsoft.Hosting.Lifetime",
  "Message": "Content root path: .\\snippets\\logging\\console-formatter-json",
  "State": {
    "Message": "Content root path: .\\snippets\\logging\\console-formatter-json",
    "contentRoot": ".\\snippets\\logging\\console-formatter-json",
    "{OriginalFormat}": "Content root path: {contentRoot}"
  }
}

팁 (조언)

Json 콘솔 포맷터는 기본적으로 각 메시지를 한 줄로 기록합니다. 포맷터를 구성할 때 더 읽기 쉽게 하려면 JsonWriterOptions.Indentedtrue로 설정하십시오.

주의

Json 콘솔 포맷터를 사용하는 경우 이미 JSON으로 serialize된 로그 메시지를 전달하지 마세요. 로깅 인프라 자체는 이미 로그 메시지의 serialization을 관리하므로 이미 serialize된 로그 메시지를 전달하려는 경우 이중 직렬화되어 잘못된 형식의 출력이 발생합니다.

구성을 사용하여 포맷터 설정

이전 샘플에서는 프로그래밍 방식으로 포맷터를 등록하는 방법을 보여 줍니다. 또는 구성을 사용하여 이 작업을 수행할 수 있습니다. 이전 웹 애플리케이션 샘플 소스 코드를 고려합니다. Program.cs 파일에서 호출 ConfigureLogging 하지 않고 appsettings.json 파일을 업데이트하면 동일한 결과를 얻을 수 있습니다. 업데이트 appsettings.json 된 파일은 다음과 같이 포맷터를 구성합니다.

{
    "Logging": {
        "LogLevel": {
            "Default": "Information",
            "Microsoft": "Warning",
            "Microsoft.Hosting.Lifetime": "Information"
        },
        "Console": {
            "LogLevel": {
                "Default": "Information",
                "Microsoft": "Warning",
                "Microsoft.Hosting.Lifetime": "Information"
            },
            "FormatterName": "json",
            "FormatterOptions": {
                "SingleLine": true,
                "IncludeScopes": true,
                "TimestampFormat": "HH:mm:ss ",
                "UseUtcTimestamp": true,
                "JsonWriterOptions": {
                    "Indented": true
                }
            }
        }
    },
    "AllowedHosts": "*"
}

설정해야 하는 두 가지 키 값은 다음과 "FormatterName"같습니다"FormatterOptions". 값이 설정된 "FormatterName" 포맷터가 이미 등록된 경우 해당 포맷터가 선택되고 노드 내에서 "FormatterOptions" 키로 제공되는 한 해당 속성을 구성할 수 있습니다. 미리 정의된 포맷터 이름은 ConsoleFormatterNames 아래에 예약되어 있습니다:

사용자 지정 포맷터 구현

사용자 지정 포맷터를 구현하려면 다음을 수행해야 합니다.

이 작업을 처리하는 확장 메서드를 만듭니다.

using Microsoft.Extensions.Logging;

namespace Console.ExampleFormatters.Custom;

public static class ConsoleLoggerExtensions
{
    public static ILoggingBuilder AddCustomFormatter(
        this ILoggingBuilder builder,
        Action<CustomOptions> configure) =>
        builder.AddConsole(options => options.FormatterName = "customName")
            .AddConsoleFormatter<CustomFormatter, CustomOptions>(configure);
}

다음과 CustomOptions 같이 정의됩니다.

using Microsoft.Extensions.Logging.Console;

namespace Console.ExampleFormatters.Custom;

public sealed class CustomOptions : ConsoleFormatterOptions
{
    public string? CustomPrefix { get; set; }
}

앞의 코드에서 옵션은 .의 ConsoleFormatterOptions하위 클래스입니다.

AddConsoleFormatter API:

  • 의 하위 클래스를 등록합니다. ConsoleFormatter
  • 구성을 처리합니다.
using Console.ExampleFormatters.Custom;
using Microsoft.Extensions.Logging;

using ILoggerFactory loggerFactory =
    LoggerFactory.Create(builder =>
        builder.AddCustomFormatter(options =>
            options.CustomPrefix = " ~~~~~ "));

ILogger<Program> logger = loggerFactory.CreateLogger<Program>();
using (logger.BeginScope("TODO: Add logic to enable scopes"))
{
    logger.LogInformation("Hello World!");
    logger.LogInformation("TODO: Add logic to enable timestamp and log level info.");
}

CustomFormatter의 하위 클래스를 ConsoleFormatter로 정의하십시오:

using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Logging.Console;
using Microsoft.Extensions.Options;

namespace Console.ExampleFormatters.Custom;

public sealed class CustomFormatter : ConsoleFormatter, IDisposable
{
    private readonly IDisposable? _optionsReloadToken;
    private CustomOptions _formatterOptions;

    public CustomFormatter(IOptionsMonitor<CustomOptions> options)
        // Case insensitive
        : base("customName") =>
        (_optionsReloadToken, _formatterOptions) =
            (options.OnChange(ReloadLoggerOptions), options.CurrentValue);

    private void ReloadLoggerOptions(CustomOptions options) =>
        _formatterOptions = options;

    public override void Write<TState>(
        in LogEntry<TState> logEntry,
        IExternalScopeProvider? scopeProvider,
        TextWriter textWriter)
    {
        string? message =
            logEntry.Formatter?.Invoke(
                logEntry.State, logEntry.Exception);

        if (message is null)
        {
            return;
        }

        CustomLogicGoesHere(textWriter);
        textWriter.WriteLine(message);
    }

    private void CustomLogicGoesHere(TextWriter textWriter)
    {
        textWriter.Write(_formatterOptions.CustomPrefix);
    }

    public void Dispose() => _optionsReloadToken?.Dispose();
}

앞의 CustomFormatter.Write<TState> API는 각 로그 메시지 주위에 래핑되는 텍스트를 지정합니다. 표준 ConsoleFormatter은 최소한 범위, 타임스탬프, 로그의 심각도 수준을 감쌀 수 있어야 합니다. 또한 로그 메시지에서 ANSI 색을 인코딩하고 원하는 들여쓰기도 제공할 수 있습니다. 구현에는 CustomFormatter.Write<TState> 이러한 기능이 부족합니다.

서식을 추가로 사용자 지정하는 방법은 네임스페이스의 기존 구현을 Microsoft.Extensions.Logging.Console 참조하세요.

사용자 지정 구성 옵션

로깅 확장성을 추가로 사용자 지정하려면 모든 ConsoleFormatterOptions에서 파생 클래스를 구성할 수 있습니다. 예를 들어 JSON 구성 공급자 를 사용하여 사용자 지정 옵션을 정의할 수 있습니다. 먼저 서브클래스를 정의합니다 ConsoleFormatterOptions .

using Microsoft.Extensions.Logging.Console;

namespace Console.ExampleFormatters.CustomWithConfig;

public sealed class CustomWrappingConsoleFormatterOptions : ConsoleFormatterOptions
{
    public string? CustomPrefix { get; set; }

    public string? CustomSuffix { get; set; }
}

앞의 콘솔 포맷터 옵션 클래스는 접두사와 접미사를 나타내는 두 개의 사용자 지정 속성을 정의합니다. 다음으로, 콘솔 포맷터 옵션을 구성할 appsettings.json 파일을 정의합니다.

{
    "Logging": {
        "LogLevel": {
            "Default": "Information",
            "Microsoft": "Warning",
            "Microsoft.Hosting.Lifetime": "Information"
        },
        "Console": {
            "LogLevel": {
                "Default": "Information",
                "Microsoft": "Warning",
                "Microsoft.Hosting.Lifetime": "Information"
            },
            "FormatterName": "CustomTimePrefixingFormatter",
            "FormatterOptions": {
                "CustomPrefix": "|-<[",
                "CustomSuffix": "]>-|",
                "SingleLine": true,
                "IncludeScopes": true,
                "TimestampFormat": "HH:mm:ss.ffff ",
                "UseUtcTimestamp": true,
                "JsonWriterOptions": {
                    "Indented": true
                }
            }
        }
    },
    "AllowedHosts": "*"
}

이전 JSON 구성 파일에서 다음을 수행합니다.

  • 노드 "Logging""Console"을 정의합니다.
  • 노드는 "Console"를 사용자 지정 포맷터에 매핑하는 "FormatterName"을 지정합니다.
  • "FormatterOptions" 노드는 "CustomPrefix", "CustomSuffix" 및 몇 가지 다른 파생 옵션을 정의합니다.

팁 (조언)

$.Logging.Console.FormatterOptions JSON 경로는 예약되어 있으며, 확장 메서드를 사용하여 추가하면 ConsoleFormatterOptions에 사용자 지정으로 매핑됩니다. 이 기능은 사용 가능한 속성 외에도 사용자 지정 속성을 정의하는 기능을 제공합니다.

다음의 CustomDatePrefixingFormatter을 고려하십시오.

using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Logging.Console;
using Microsoft.Extensions.Options;

namespace Console.ExampleFormatters.CustomWithConfig;

public sealed class CustomTimePrefixingFormatter : ConsoleFormatter, IDisposable
{
    private readonly IDisposable? _optionsReloadToken;
    private CustomWrappingConsoleFormatterOptions _formatterOptions;

    public CustomTimePrefixingFormatter(
        IOptionsMonitor<CustomWrappingConsoleFormatterOptions> options)
        // Case insensitive
        : base(nameof(CustomTimePrefixingFormatter))
    {
        _optionsReloadToken = options.OnChange(ReloadLoggerOptions);
        _formatterOptions = options.CurrentValue;
    }

    private void ReloadLoggerOptions(CustomWrappingConsoleFormatterOptions options) =>
        _formatterOptions = options;

    public override void Write<TState>(
        in LogEntry<TState> logEntry,
        IExternalScopeProvider? scopeProvider,
        TextWriter textWriter)
    {
        string message =
            logEntry.Formatter(
                logEntry.State, logEntry.Exception);

        if (message == null)
        {
            return;
        }

        WritePrefix(textWriter);
        textWriter.Write(message);
        WriteSuffix(textWriter);
    }

    private void WritePrefix(TextWriter textWriter)
    {
        DateTime now = _formatterOptions.UseUtcTimestamp
            ? DateTime.UtcNow
            : DateTime.Now;

        textWriter.Write($"""
            {_formatterOptions.CustomPrefix} {now.ToString(_formatterOptions.TimestampFormat)}
            """);
    }

    private void WriteSuffix(TextWriter textWriter) =>
        textWriter.WriteLine($" {_formatterOptions.CustomSuffix}");

    public void Dispose() => _optionsReloadToken?.Dispose();
}

이전 포맷터 구현에서:

사용자 지정 포맷터 구현과 함께 사용자 지정 구성 옵션을 사용하려면 호출 ConfigureLogging(IHostBuilder, Action<HostBuilderContext,ILoggingBuilder>)할 때 추가합니다.

using Console.ExampleFormatters.CustomWithConfig;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;

HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);

builder.Logging.AddConsole()
    .AddConsoleFormatter<
        CustomTimePrefixingFormatter, CustomWrappingConsoleFormatterOptions>();

using IHost host = builder.Build();

ILoggerFactory loggerFactory = host.Services.GetRequiredService<ILoggerFactory>();
ILogger<Program> logger = loggerFactory.CreateLogger<Program>();

using (logger.BeginScope("Logging scope"))
{
    logger.LogInformation("Hello World!");
    logger.LogInformation("The .NET developer community happily welcomes you.");
}

다음 콘솔 출력은 이 CustomTimePrefixingFormatter출력을 사용할 때 예상되는 것과 유사합니다.

|-<[ 15:03:15.6179 Hello World! ]>-|
|-<[ 15:03:15.6347 The .NET developer community happily welcomes you. ]>-|

사용자 지정 색 서식 구현

사용자 지정 로깅 포맷터에서 색 기능을 올바르게 사용하도록 설정하려면, SimpleConsoleFormatterOptions를 확장할 수 있습니다. 이는 로그에서 색을 사용하도록 설정하는 데 유용할 수 있는 SimpleConsoleFormatterOptions.ColorBehavior 속성을 포함하고 있기 때문입니다.

CustomColorOptions에서 파생된 SimpleConsoleFormatterOptions을 만드세요.

using Microsoft.Extensions.Logging.Console;

namespace Console.ExampleFormatters.Custom;

public class CustomColorOptions : SimpleConsoleFormatterOptions
{
    public string? CustomPrefix { get; set; }
}

다음으로 형식이 지정된 로그 메시지 내에 ANSI 코딩된 색을 편리하게 포함할 수 있는 몇 가지 확장 메서드 TextWriterExtensions 를 클래스에 작성합니다.

namespace Console.ExampleFormatters.Custom;

public static class TextWriterExtensions
{
    const string DefaultForegroundColor = "\x1B[39m\x1B[22m";
    const string DefaultBackgroundColor = "\x1B[49m";

    public static void WriteWithColor(
        this TextWriter textWriter,
        string message,
        ConsoleColor? background,
        ConsoleColor? foreground)
    {
        // Order:
        //   1. background color
        //   2. foreground color
        //   3. message
        //   4. reset foreground color
        //   5. reset background color

        var backgroundColor = background.HasValue ? GetBackgroundColorEscapeCode(background.Value) : null;
        var foregroundColor = foreground.HasValue ? GetForegroundColorEscapeCode(foreground.Value) : null;

        if (backgroundColor != null)
        {
            textWriter.Write(backgroundColor);
        }
        if (foregroundColor != null)
        {
            textWriter.Write(foregroundColor);
        }

        textWriter.WriteLine(message);

        if (foregroundColor != null)
        {
            textWriter.Write(DefaultForegroundColor);
        }
        if (backgroundColor != null)
        {
            textWriter.Write(DefaultBackgroundColor);
        }
    }

    static string GetForegroundColorEscapeCode(ConsoleColor color) =>
        color switch
        {
            ConsoleColor.Black => "\x1B[30m",
            ConsoleColor.DarkRed => "\x1B[31m",
            ConsoleColor.DarkGreen => "\x1B[32m",
            ConsoleColor.DarkYellow => "\x1B[33m",
            ConsoleColor.DarkBlue => "\x1B[34m",
            ConsoleColor.DarkMagenta => "\x1B[35m",
            ConsoleColor.DarkCyan => "\x1B[36m",
            ConsoleColor.Gray => "\x1B[37m",
            ConsoleColor.Red => "\x1B[1m\x1B[31m",
            ConsoleColor.Green => "\x1B[1m\x1B[32m",
            ConsoleColor.Yellow => "\x1B[1m\x1B[33m",
            ConsoleColor.Blue => "\x1B[1m\x1B[34m",
            ConsoleColor.Magenta => "\x1B[1m\x1B[35m",
            ConsoleColor.Cyan => "\x1B[1m\x1B[36m",
            ConsoleColor.White => "\x1B[1m\x1B[37m",

            _ => DefaultForegroundColor
        };

    static string GetBackgroundColorEscapeCode(ConsoleColor color) =>
        color switch
        {
            ConsoleColor.Black => "\x1B[40m",
            ConsoleColor.DarkRed => "\x1B[41m",
            ConsoleColor.DarkGreen => "\x1B[42m",
            ConsoleColor.DarkYellow => "\x1B[43m",
            ConsoleColor.DarkBlue => "\x1B[44m",
            ConsoleColor.DarkMagenta => "\x1B[45m",
            ConsoleColor.DarkCyan => "\x1B[46m",
            ConsoleColor.Gray => "\x1B[47m",

            _ => DefaultBackgroundColor
        };
}

사용자 지정 색 적용을 처리하는 사용자 지정 색 포맷터는 다음과 같이 정의할 수 있습니다.

using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Logging.Console;
using Microsoft.Extensions.Options;

namespace Console.ExampleFormatters.Custom;

public sealed class CustomColorFormatter : ConsoleFormatter, IDisposable
{
    private readonly IDisposable? _optionsReloadToken;
    private CustomColorOptions _formatterOptions;

    private bool ConsoleColorFormattingEnabled =>
        _formatterOptions.ColorBehavior == LoggerColorBehavior.Enabled ||
        _formatterOptions.ColorBehavior == LoggerColorBehavior.Default &&
        System.Console.IsOutputRedirected == false;

    public CustomColorFormatter(IOptionsMonitor<CustomColorOptions> options)
        // Case insensitive
        : base("customName") =>
        (_optionsReloadToken, _formatterOptions) =
            (options.OnChange(ReloadLoggerOptions), options.CurrentValue);

    private void ReloadLoggerOptions(CustomColorOptions options) =>
        _formatterOptions = options;

    public override void Write<TState>(
        in LogEntry<TState> logEntry,
        IExternalScopeProvider? scopeProvider,
        TextWriter textWriter)
    {
        if (logEntry.Exception is null)
        {
            return;
        }

        string? message =
            logEntry.Formatter?.Invoke(
                logEntry.State, logEntry.Exception);

        if (message is null)
        {
            return;
        }

        CustomLogicGoesHere(textWriter);
        textWriter.WriteLine(message);
    }

    private void CustomLogicGoesHere(TextWriter textWriter)
    {
        if (ConsoleColorFormattingEnabled)
        {
            textWriter.WriteWithColor(
                _formatterOptions.CustomPrefix ?? string.Empty,
                ConsoleColor.Black,
                ConsoleColor.Green);
        }
        else
        {
            textWriter.Write(_formatterOptions.CustomPrefix);
        }
    }

    public void Dispose() => _optionsReloadToken?.Dispose();
}

애플리케이션을 실행하면 로그에 메시지가 녹색 CustomPrefixFormatterOptions.ColorBehavior으로 표시됩니다Enabled.

비고

LoggerColorBehaviorDisabled일 때, 로그 메시지는 로그 메시지 내에 포함된 ANSI 색상 코드를 해석하지 않습니다. 대신 원시 메시지를 출력합니다. 예를 들어 다음을 고려합니다.

logger.LogInformation("Random log \x1B[42mwith green background\x1B[49m message");

색상이 지정되지 않고 그러면 문자열이 그대로 출력됩니다.

Random log \x1B[42mwith green background\x1B[49m message

참고하십시오