次の方法で共有


コンソール ログの書式設定

.NET 5 では、カスタム書式設定のサポートが、 Microsoft.Extensions.Logging.Console 名前空間のコンソール ログに追加されました。 定義済みの書式設定オプションには、 SimpleSystemdJsonの 3 つがあります。

Von Bedeutung

以前は、 ConsoleLoggerFormat 列挙型は、目的のログ形式 ( Defaultである人間が判読可能か、または Systemd とも呼ばれる 1 行) を選択することができました。 ただし、これらはカスタマイズ 可能ではなく 、現在は非推奨になっています。

この記事では、コンソール ログ フォーマッタについて説明します。 サンプル ソース コードでは、次の方法を示します。

  • 新しいフォーマッタを登録する
  • 使用する登録済みフォーマッタを選択する
    • コードを使用するか、構成を用いる
  • カスタム フォーマッタを実装する

ヒント

ログのサンプル ソース コードはすべて、サンプル ブラウザーでダウンロードできます。 詳細については、コード サンプルの参照: .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" のログレベル形式とその重大度を使用します。
  • メッセージを色で書式設定しない
  • 常に 1 行でメッセージを記録する

これは、多くの場合、 Systemd コンソールのログ記録を利用するコンテナーに役立ちます。 .NET 5 では、 Simple コンソール ロガーを使用すると、1 行でログに記録するコンパクトなバージョンも可能になり、前のサンプルに示すように色を無効にすることもできます。

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 コンソール ログ フォーマッタは既定の構成で選択されます。 これを変更するには、Program.csで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 コンソール フォーマッタは、既定では、各メッセージを 1 行に記録します。 フォーマッタの構成中に読みやすくするには、 JsonWriterOptions.Indentedtrue に設定します。

注意事項

Json コンソール フォーマッタを使用する場合は、既に JSON としてシリアル化されているログ メッセージを渡さないでください。 ログ 記録インフラストラクチャ自体は既にログ メッセージのシリアル化を管理しているため、既にシリアル化されているログ メッセージを渡す場合は、二重シリアル化されるため、出力の形式が正しくありません。

構成を使用してフォーマッタを設定する

前のサンプルでは、フォーマッタをプログラムで登録する方法を示しました。 または、 構成を使用してこれを行うことができます。 前の Web アプリケーションサンプルのソース コードを考えてみましょう。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": "*"
}

設定する必要がある 2 つの主要な値は、 "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 のサブクラスです。

API(エーピーアイ)AddConsoleFormatter:

  • のサブクラスを登録します。 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.");
}

CustomFormatterConsoleFormatter サブクラスを定義します。

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; }
}

上記のコンソール フォーマッタ オプション クラスは、プレフィックスとサフィックスを表す 2 つのカスタム プロパティを定義します。 次に、コンソール フォーマッタ オプションを構成する 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""CustomTimePrefixingFormatter"を指定します。
  • "FormatterOptions" ノードでは、"CustomPrefix""CustomSuffix"のほか、他のいくつかの派生オプションが定義されます。

ヒント

$.Logging.Console.FormatterOptions JSON パスは予約されており、ConsoleFormatterOptions拡張メソッドを使用して追加すると、カスタム AddConsoleFormatterにマップされます。 これにより、使用可能なプロパティに加えて、カスタム プロパティを定義する機能が提供されます。

次の 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();
}

前のフォーマッタの実装では、次のようになります。

  • CustomWrappingConsoleFormatterOptionsは変更を監視し、それに応じて更新されます。
  • 書き込まれるメッセージは、構成済みのプレフィックスとサフィックスでラップされます。
  • タイムスタンプはプレフィックスの後に追加されますが、構成された ConsoleFormatterOptions.UseUtcTimestamp 値と ConsoleFormatterOptions.TimestampFormat 値を使用してメッセージの前に追加されます。

カスタムフォーマッタの実装でカスタム構成オプションを使用するには、 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

こちらも参照ください