Megosztás a következőn keresztül:


Konzolnapló formázása

A .NET 5-ben az egyéni formázás támogatása a névtérben Microsoft.Extensions.Logging.Console lévő konzolnaplókhoz lett hozzáadva. Három előre definiált formázási lehetőség érhető el: Simple, Systemdés Json.

Fontos

Korábban az ConsoleLoggerFormat enumerálás lehetővé tette a kívánt naplóformátum kiválasztását, akár emberi olvasható, akár egysoros Default, más néven Systemd. Ezek azonban nem testreszabhatók, és most elavultak.

Ebben a cikkben megismerkedhet a konzolnapló-formázókkal. A minta forráskódja bemutatja, hogyan:

  • Új formázó regisztrálása
  • Válasszon egy használni kívánt regisztrált formázót
  • Egyéni formázó implementálása

Tipp.

Az összes naplózási példa forráskódja letölthető a Mintaböngészőben . További információ: Kódminták tallózása: Naplózás a .NET-ben.

Formatter regisztrálása

A Console naplózási szolgáltató számos előre definiált formázóval rendelkezik, és lehetővé teszi saját egyéni formázó készítését. Az elérhető formázók regisztrálásához használja a megfelelő Add{Type}Console bővítménymetódust:

Elérhető típusok Típus regisztrálásának módja
ConsoleFormatterNames.Json ConsoleLoggerExtensions.AddJsonConsole
ConsoleFormatterNames.Simple ConsoleLoggerExtensions.AddSimpleConsole
ConsoleFormatterNames.Systemd ConsoleLoggerExtensions.AddSystemdConsole

Egyszerű

A Simple konzolformátumító használatához regisztrálja a következővel 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.");
}

Az előző minta forráskódjában a ConsoleFormatterNames.Simple formázó regisztrálva lett. A naplók lehetővé teszik, hogy ne csak az egyes naplóüzenetekbe becsomagolja az információkat, például az időt és a naplószintet, hanem lehetővé teszi az ÜZENETEK ANSI-színbe ágyazását és behúzását is.

A mintaalkalmazás futtatásakor a naplóüzenetek az alábbi módon lesznek formázva:

Példa konzolnaplókra, amelyek az egyszerű formázóval íródnak.

Rendszerezett

A ConsoleFormatterNames.Systemd konzolnaplózó:

  • A "Syslog" naplószintű formátumot és súlyosságokat használja
  • Nem formázza a színekkel rendelkező üzeneteket
  • Üzenetek mindig egyetlen sorban naplózva

Ez gyakran hasznos tárolók esetében, amelyek gyakran használják a konzolnaplózást Systemd . A .NET 5-tel a Simple konzolnaplózó egy olyan kompakt verziót is lehetővé tesz, amely egyetlen sorban naplóz, és lehetővé teszi a színek letiltását is egy korábbi mintában látható módon.

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

A példa a következő naplóüzenetekhez hasonló kimenetet hoz létre:

Példa konzolnaplókra, amelyek a Systemd formatterrel íródtak.

Json

A naplók JSON formátumú írásához a Json konzolformázó használható. A minta forráskódja bemutatja, hogyan regisztrálhatja egy ASP.NET Core-alkalmazás. webapp A sablon használatával hozzon létre egy új ASP.NET Core-alkalmazást az új dotnet paranccsal:

dotnet new webapp -o Console.ExampleFormatters.Json

Az alkalmazás futtatásakor a sablonkód használatával az alábbi alapértelmezett naplóformátumot kapja:

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

Alapértelmezés szerint a Simple konzolnapló-formázó van kiválasztva az alapértelmezett konfigurációval. Ezt a Program.cs hívásával AddJsonConsolemódosíthatja:

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

Ezt a naplózási konfigurációval is konfigurálhatja, például a appsettings.json fájlban:

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

Futtassa újra az alkalmazást, a fenti módosítással a naplóüzenet mostantól JSON formátumban van formázva:

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

Tipp.

A Json konzolforma-formázó alapértelmezés szerint egyetlen sorban naplózza az egyes üzeneteket. Annak érdekében, hogy olvashatóbb legyen a formázó konfigurálása során, állítsa a JsonWriterOptions.Indented következőre true: .

Figyelemfelhívás

A Json-konzolformázó használatakor ne adjon át olyan naplóüzeneteket, amelyeket már szerializáltak JSON-ként. Maga a naplózási infrastruktúra már kezeli a naplóüzenetek szerializálását, így ha egy már szerializált naplóüzenetet szeretne átadni, az duplán szerializálódik, ami hibás kimenetet okoz.

Formázó beállítása konfigurációval

Az előző minták bemutatják, hogyan regisztrálhat programozott módon egy formázót. Ezt a konfigurációval is megteheti. Vegye figyelembe az előző webalkalmazás-minta forráskódot, ha a appsettings.json fájlt frissíti ahelyett ConfigureLogging , hogy meghívná a Program.cs fájlt, ugyanezt az eredményt érheti el. A frissített appsettings.json fájl a következőképpen konfigurálja a formázót:

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

A két kulcsérték, amelyeket be kell állítani, és "FormatterOptions"."FormatterName" Ha már regisztrálva van egy olyan formázó, amelynek az értéke meg "FormatterName" van adva, akkor a program kijelöli a formátumot, és a tulajdonságai konfigurálhatók mindaddig, amíg kulcsként vannak megadva a "FormatterOptions" csomóponton belül. Az előre definiált formázónevek a következő területen ConsoleFormatterNamesvannak fenntartva:

Egyéni formázó implementálása

Egyéni formázó implementálásához a következőkre van szükség:

Hozzon létre egy bővítménymetódust a kezeléshez:

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

A CustomOptions definíció a következő:

using Microsoft.Extensions.Logging.Console;

namespace Console.ExampleFormatters.Custom;

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

Az előző kódban a beállítások a ConsoleFormatterOptions.

Az AddConsoleFormatter API:

  • A alosztályát regisztrálja ConsoleFormatter
  • Kezeli a konfigurációt:
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 A következő alosztály definiálásaConsoleFormatter:

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

Az előző CustomFormatter.Write<TState> API határozza meg, hogy az egyes naplóüzenetek milyen szövegbe burkolhatók. Egy szabványnak ConsoleFormatter legalább a hatókörök, az időbélyegek és a naplók súlyossági szintje körül kell tudnia körbefutni. Emellett a naplóüzenetekben ANSI-színeket is kódolhat, és a kívánt behúzásokat is megadhat. A megvalósítás nem rendelkezik ezekkel a CustomFormatter.Write<TState> képességekkel.

A formázás további testreszabásával kapcsolatos inspirációért tekintse meg a névtér meglévő Microsoft.Extensions.Logging.Console implementációit:

Egyéni konfigurációs beállítások

A naplózás bővíthetőségének további testreszabásához a származtatott ConsoleFormatterOptions osztály bármely konfigurációszolgáltatótól konfigurálható. Használhatja például a JSON-konfigurációszolgáltatót az egyéni beállítások meghatározásához. Először határozza meg az alosztályt 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; }
}

Az előző konzolformátum-beállításosztály két egyéni tulajdonságot határoz meg, amelyek egy előtagot és utótagot jelölnek. Ezután adja meg a appsettings.json fájlt, amely konfigurálja a konzolformázási beállításokat.

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

Az előző JSON-konfigurációs fájlban:

  • A "Logging" csomópont definiál egy "Console".
  • A "Console" csomópont az "FormatterName" egyiket "CustomTimePrefixingFormatter"adja meg, amely egy egyéni formázóhoz lesz leképezve.
  • A "FormatterOptions" csomópont definiál egy "CustomPrefix", és "CustomSuffix", valamint néhány más származtatott lehetőséget.

Tipp.

A $.Logging.Console.FormatterOptions JSON-elérési út fenntartott, és a bővítménymetódus használatával hozzáadva egy egyénire ConsoleFormatterOptions lesz megfeleltetve AddConsoleFormatter . Így az elérhető tulajdonságok mellett egyéni tulajdonságokat is meghatározhat.

Vegye figyelembe a következőket 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();
}

Az előző formázási implementációban:

Ha egyéni konfigurációs beállításokat szeretne használni, egyéni formázó implementációkkal, adja hozzá híváskor 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.");
}

A következő konzolkimenet hasonló ahhoz, amit elvárhat a használattól CustomTimePrefixingFormatter.

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

Egyéni színformázás implementálása

Annak érdekében, hogy megfelelően engedélyezze a színfunkciókat az egyéni naplózási formátumszolgáltatóban, kibővítheti a SimpleConsoleFormatterOptions tulajdonságot, SimpleConsoleFormatterOptions.ColorBehavior amely hasznos lehet a naplók színeinek engedélyezéséhez.

Hozzon létre egy olyant CustomColorOptions , amely a következőből SimpleConsoleFormatterOptionsszármazik:

using Microsoft.Extensions.Logging.Console;

namespace Console.ExampleFormatters.Custom;

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

Ezután írjon néhány bővítménymetelyt egy TextWriterExtensions osztályba, amely lehetővé teszi az ANSI-kódolt színek kényelmes beágyazását a formázott naplóüzenetekbe:

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

Az egyéni színeket kezelő egyéni színformáló a következőképpen definiálható:

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

Az alkalmazás futtatásakor a naplók zöld színnel jelenítik meg az CustomPrefix üzenetet, ha FormatterOptions.ColorBehavior igen Enabled.

Feljegyzés

Ha LoggerColorBehavior igen, a Disablednaplóüzenetek nem értelmezik a beágyazott ANSI-színkódokat a naplóüzenetekben. Ehelyett a nyers üzenetet adják ki. Vegyük például a következőket:

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

Ez a szó szerinti sztringet adja ki, és nincs színezve.

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

Lásd még