Sdílet prostřednictvím


Formátování protokolu konzoly

Obor Microsoft.Extensions.Logging.Console názvů poskytuje podporu vlastního formátování v protokolech konzoly. K dispozici jsou tři předdefinované možnosti formátování: Simple, Systemda Json.

Důležité

Před .NET 5 výčet ConsoleLoggerFormat umožňoval výběr požadovaného formátu protokolu, buď čitelný pro lidi, což bylo Default, nebo jednořádkový, který se označuje také 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:

  • Zaregistrujte nový formátovací modul.
  • Vyberte registrovaný formátovací modul, který se má použít prostřednictvím kódu nebo konfigurace.
  • Implementujte vlastní formátovací modul. Konfiguraci aktualizujete prostřednictvím IOptionsMonitor<TOptions> a povolíte vlastní formátování barev.

Návod

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.

Formátovač registru

ZprostředkovatelConsole 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

Simple

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 byl formátovač ConsoleFormatterNames.Simple 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 protokolu a úrovně závažnosti 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í záznamy konzole Systemd. Nástroj Simple pro protokolování konzoly umožňuje také kompaktní verzi, která se protokoluje na jednom řádku, a umožňuje rovněž 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í je formátovací modul protokolu konzoly Simple 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í, například pomocí konfigurace nalezené v souboruappsettings.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}"
  }
}

Návod

Formátovací Json modul konzoly ve výchozím nastavení zaznamená každou zprávu do jednoho řádku. Pokud chcete, aby byl během konfigurace formátovače čitelnější, nastavte JsonWriterOptions.Indented k true.

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í spravuje serializaci zpráv protokolu. Takže pokud předáte zprávu protokolu, která je již serializována, bude dvojitě serializována, což způsobuje poškozený výstup.

Nastavte formátovač pomocí konfigurace

Předchozí ukázky ukázaly, jak programově zaregistrovat formátovací modul. Případně to můžete provést s konfigurací. Zvažte předchozí zdrojový kód webové aplikace, pokud aktualizujete soubor appsettings.json místo volání ConfigureLogging v souboru Program.cs, můžete dosáhnout stejného výsledku. 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 rozšiřující metodu, která to za vás 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);
}

Tyto CustomOptions jsou 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 obklopuje každou zprávu protokolu. Standard ConsoleFormatter by měl být schopný zahrnovat rozsahy, časová razítka 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 CustomFormatter.Write<TState> postrádá tyto schopnosti.

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 appsettings.json soubor, 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", který se mapuje na vlastní formátovač.
  • Uzel "FormatterOptions" definuje "CustomPrefix" a "CustomSuffix", stejně jako několik dalších odvozených možností.

Návod

Cesta $.Logging.Console.FormatterOptions JSON je vyhrazená a při přidání pomocí ConsoleFormatterOptions metody rozšíření se mapuje na vlastníAddConsoleFormatter. 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 konzole je podobný tomu, co byste mohli očekávat při 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 CustomColorOptions, které je odvozeno od 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í zpráva CustomPrefix v zelené barvě, když FormatterOptions.ColorBehavior je Enabled.

Poznámka:

Když je LoggerColorBehaviorDisabled, protokolové zprávy neinterpretují vložené kódy barev ANSI. 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é