Sdílet prostřednictvím


Formátování protokolu konzoly

V .NET 5 byla podpora vlastního formátování přidána do protokolů konzoly v Microsoft.Extensions.Logging.Console oboru názvů. K dispozici jsou tři předdefinované možnosti formátování: Simple, Systemda Json.

Důležité

ConsoleLoggerFormat Dříve byl výčet povolený pro výběr požadovaného formátu protokolu, a to buď člověk čitelný, který byl Default, nebo jeden řádek, který je také známý jako Systemd. Tyto možnosti ale nebyly přizpůsobitelné a jsou zastaralé.

V tomto článku se dozvíte o formátovacích protokolech konzoly. Ukázkový zdrojový kód ukazuje, jak:

  • Registrace nového formátovače
  • Výběr registrovaného formátovače, který se má použít
  • Implementace vlastního formátovače

Tip

Veškerý zdrojový kód příkladu protokolování je k dispozici v prohlížeči ukázek ke stažení. Další informace najdete v tématu Procházení ukázek kódu: Protokolování v .NET.

Registrovat formátovací modul

Zprostředkovatel Console protokolování má několik předdefinovaných formátovacích nástrojů a zpřístupňuje možnost vytvořit vlastní formátovací modul. Pokud chcete zaregistrovat některý z dostupných formátovacích souborů, použijte odpovídající Add{Type}Console metodu rozšíření:

Dostupné typy Metoda registrace typu
ConsoleFormatterNames.Json ConsoleLoggerExtensions.AddJsonConsole
ConsoleFormatterNames.Simple ConsoleLoggerExtensions.AddSimpleConsole
ConsoleFormatterNames.Systemd ConsoleLoggerExtensions.AddSystemdConsole

Stručně

Chcete-li použít Simple formátovací modul konzoly, zaregistrujte ho v 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.");
}

V předchozím ukázkovém zdrojovém kódu ConsoleFormatterNames.Simple byl formátovač zaregistrován. Poskytuje protokoly s možností nejen zalamovat informace, jako je čas a úroveň protokolu v každé zprávě protokolu, ale také umožňuje vkládání barev ANSI a odsazení zpráv.

Při spuštění této ukázkové aplikace se zprávy protokolu naformátují, jak je znázorněno níže:

Ukázkové protokoly konzoly napsané pomocí jednoduchého formátovače

Systemd

Protokolovací ConsoleFormatterNames.Systemd služba konzoly:

  • Používá formát a závažnosti na úrovni protokolu Syslog.
  • Neformátuje zprávy pomocí barev.
  • Vždy protokoluje zprávy na jednom řádku.

To je běžně užitečné pro kontejnery, které často využívají Systemd protokolování konzoly. Pomocí rozhraní .NET 5 Simple protokolovací nástroj konzoly také umožňuje kompaktní verzi, která se protokoluje na jednom řádku, a také umožňuje zakázat barvy, jak je znázorněno v předchozí ukázce.

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.");
}

Příklad vytvoří výstup podobný následujícím zprávám protokolu:

Ukázkové protokoly konzoly napsané pomocí systémového formátovače

JSON

K zápisu protokolů ve formátu Json JSON se použije formátovací modul konzoly. Ukázkový zdrojový kód ukazuje, jak ji aplikace ASP.NET Core může zaregistrovat. webapp Pomocí šablony vytvořte novou aplikaci ASP.NET Core pomocí nového příkazu dotnet:

dotnet new webapp -o Console.ExampleFormatters.Json

Při spuštění aplikace pomocí kódu šablony získáte následující výchozí formát protokolu:

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

Ve výchozím nastavení Simple je formátovací modul protokolu konzoly vybraný s výchozí konfigurací. Toto nastavení změníte voláním AddJsonConsole do Program.cs:

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();

Případně můžete tuto konfiguraci nakonfigurovat také pomocí konfigurace protokolování, jako je například konfigurace nalezená v souboru 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": "*"
}

Znovu spusťte aplikaci s výše uvedenou změnou, zpráva protokolu je teď naformátovaná jako 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}"
  }
}

Tip

Formátovací Json modul konzoly ve výchozím nastavení zaznamená každou zprávu do jednoho řádku. Aby byl při konfiguraci formátovače čitelnější, nastavte JsonWriterOptions.Indented na truehodnotu .

Upozornění

Pokud používáte formátovací modul konzoly Json, nepředávejte zprávy protokolu, které už byly serializovány jako JSON. Samotná infrastruktura protokolování už spravuje serializaci zpráv protokolu, takže pokud chcete předat zprávu protokolu, která je již serializovaná– bude dvojitě serializována, což způsobuje poškozený výstup.

Nastavení formátovače s konfigurací

Předchozí ukázky ukázaly, jak programově zaregistrovat formátovací modul. Případně to můžete provést s konfigurací. Pokud aktualizujete soubor appsettings.json místo volání ConfigureLogging do souboru Program.cs, zvažte předchozí zdrojový kód webové aplikace, můžete získat stejný výsledek. Aktualizovaný appsettings.json soubor by nakonfiguroval formátovací modul následujícím způsobem:

{
    "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": "*"
}

Dvě hodnoty klíče, které je potřeba nastavit, jsou "FormatterName" a "FormatterOptions". Pokud je formátovací modul s hodnotou nastavenou pro "FormatterName" již zaregistrovaný, je tento formátovací modul vybrán a jeho vlastnosti lze nakonfigurovat, pokud jsou k dispozici jako klíč uvnitř "FormatterOptions" uzlu. Předdefinované názvy formátovačů jsou vyhrazeny v části ConsoleFormatterNames:

Implementace vlastního formátovače

Pokud chcete implementovat vlastní formátovací modul, musíte:

Vytvořte metodu rozšíření, která vám tuto metodu zpracuje:

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

Jsou CustomOptions definovány takto:

using Microsoft.Extensions.Logging.Console;

namespace Console.ExampleFormatters.Custom;

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

V předchozím kódu jsou možnosti podtřídou ConsoleFormatterOptions.

Rozhraní AddConsoleFormatter API:

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.");
}

Definujte podtřídu 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();
}

Předchozí CustomFormatter.Write<TState> rozhraní API určuje, jaký text se zalomí kolem každé zprávy protokolu. Standard ConsoleFormatter by měl být schopný obtékání rozsahů, časových razítek a úrovně závažnosti protokolů minimálně. Kromě toho můžete do zpráv protokolu zakódovat barvy ANSI a také požadované odsazení. Implementace chybějících CustomFormatter.Write<TState> schopností.

Inspiraci k dalšímu přizpůsobení formátování najdete v existujících implementacích v Microsoft.Extensions.Logging.Console oboru názvů:

Možnosti vlastní konfigurace

Chcete-li dále přizpůsobit rozšiřitelnost protokolování, je možné odvozenou ConsoleFormatterOptions třídu nakonfigurovat od libovolného zprostředkovatele konfigurace. K definování vlastních možností můžete například použít zprostředkovatele konfigurace JSON. Nejprve definujte svou ConsoleFormatterOptions podtřídu.

using Microsoft.Extensions.Logging.Console;

namespace Console.ExampleFormatters.CustomWithConfig;

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

    public string? CustomSuffix { get; set; }
}

Předchozí třída možností formátovače konzoly definuje dvě vlastní vlastnosti představující předponu a příponu. Dále definujte soubor appsettings.json , který nakonfiguruje možnosti formátovače konzoly.

{
    "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": "*"
}

V předchozím konfiguračním souboru JSON:

  • Uzel "Logging" definuje ."Console"
  • Uzel "Console" určuje "FormatterName" , z "CustomTimePrefixingFormatter"kterého se mapuje na vlastní formátovací modul.
  • Uzel "FormatterOptions" definuje a "CustomPrefix""CustomSuffix"a také několik dalších odvozených možností.

Tip

Cesta $.Logging.Console.FormatterOptions JSON je vyhrazená a při přidání pomocí AddConsoleFormatter metody rozšíření se mapuje na vlastníConsoleFormatterOptions. Díky tomu můžete kromě dostupných vlastností definovat i vlastní vlastnosti.

Zvažte následující 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();
}

V předchozí implementaci formátovače:

Chcete-li použít vlastní možnosti konfigurace s vlastními implementacemi formátovače, přidejte při volání 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.");
}

Následující výstup konzoly je podobný tomu, co byste mohli očekávat od použití .CustomTimePrefixingFormatter

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

Implementace vlastního formátování barev

Pokud chcete ve vlastním formátovacím prvku protokolování správně povolit možnosti barev, můžete rozšířit SimpleConsoleFormatterOptions , protože má SimpleConsoleFormatterOptions.ColorBehavior vlastnost, která může být užitečná pro povolení barev v protokolech.

Vytvořte odvozenou CustomColorOptions z SimpleConsoleFormatterOptions:

using Microsoft.Extensions.Logging.Console;

namespace Console.ExampleFormatters.Custom;

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

Dále do třídy napište některé rozšiřující metody TextWriterExtensions , které umožňují pohodlně vkládat barvy s kódováním ANSI do formátovaných zpráv protokolu:

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

Vlastní formátovací modul barev, který zpracovává použití vlastních barev, může být definován takto:

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

Při spuštění aplikace se v protokolech zobrazí CustomPrefix zpráva v barvě zelené, pokud FormatterOptions.ColorBehavior je Enabled.

Poznámka:

Pokud LoggerColorBehavior anoDisabled, zprávy protokolu neinterpretují vložené kódy barev ANSI v protokolových zprávách. Místo toho vypíše nezpracovanou zprávu. Představte si například následující:

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

Tím se vypíše doslovný řetězec, který není obarvený.

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

Viz také