Compartir a través de


Formato de registro de la consola

En .NET 5, se ha agregado compatibilidad con el formato personalizado a los registros de la consola en el espacio de nombres Microsoft.Extensions.Logging.Console. Hay tres opciones de formato predefinidas disponibles: Simple, Systemdy Json.

Importante

Anteriormente, la ConsoleLoggerFormat enumeración permitía seleccionar el formato de registro deseado, ya sea legible por humanos, que era la Default, o línea única, que también se conoce como Systemd. Sin embargo, estos no eran personalizables y ahora están en desuso.

En este artículo, obtendrá información sobre los formateadores de registro de consola. El código fuente de ejemplo muestra cómo:

  • Registro de un nuevo formateador
  • Selecciona un formateador registrado para usar
  • Implementación de un formateador personalizado
    • Actualización de la configuración a través de IOptionsMonitor<TOptions>
    • Habilitación del formato de color personalizado

Sugerencia

Todo el código fuente del ejemplo de registro está disponible en el Explorador de ejemplos para su descarga. Para obtener más información, consulte Explorar ejemplos de código: registro en .NET.

Formateador de registros

El Console proveedor de registro tiene varios formateadores predefinidos y ofrece la posibilidad de crear su propio formateador personalizado. Para registrar cualquiera de los formateadores disponibles, use el método de extensión correspondiente Add{Type}Console :

Tipos disponibles Método para registrar el tipo
ConsoleFormatterNames.Json ConsoleLoggerExtensions.AddJsonConsole
ConsoleFormatterNames.Simple ConsoleLoggerExtensions.AddSimpleConsole
ConsoleFormatterNames.Systemd ConsoleLoggerExtensions.AddSystemdConsole

Sencillo

Para usar el formateador de consola Simple, regístrelo con 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.");
}

En el código fuente de ejemplo anterior, se registró el formateador ConsoleFormatterNames.Simple. Proporciona registros con la posibilidad de no solo ajustar información, como el tiempo y el nivel de registro de cada mensaje de registro, sino que también permite la inserción de color ANSI y la sangría de los mensajes.

Cuando se ejecuta esta aplicación de ejemplo, los mensajes de registro tienen el formato siguiente:

Registros de consola de ejemplo escritos con el formateador simple.

Systemd

Registrador de la consola ConsoleFormatterNames.Systemd:

  • Usa el formato de nivel de registro "Syslog" y los niveles de gravedad.
  • No da formato a los mensajes con colores
  • Registra siempre los mensajes en una sola línea

Esto suele ser útil para los contenedores, que a menudo usan el registro de la consola Systemd. Con .NET 5, el Simple registrador de consola también habilita una versión compacta que registra en una sola línea y también permite deshabilitar los colores como se muestra en un ejemplo anterior.

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

En el ejemplo se genera una salida similar a los siguientes mensajes de registro:

Registros de consola de ejemplo escritos con el formateador systemd.

Json

Para escribir registros en un formato JSON, se usa el Json formateador de consola. El código fuente de ejemplo muestra cómo una aplicación ASP.NET Core puede registrarla. Con la webapp plantilla, cree una nueva aplicación ASP.NET Core con el comando dotnet new :

dotnet new webapp -o Console.ExampleFormatters.Json

Al ejecutar la aplicación, con el código de plantilla, obtendrá el formato de registro predeterminado siguiente:

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

De forma predeterminada, el Simple formateador de registro de consola está seleccionado con la configuración predeterminada. Para cambiarlo, llame a AddJsonConsole en el 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();

Como alternativa, también puede configurarlo mediante la configuración de registro, como la que se encuentra en el archivo 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": "*"
}

Vuelva a ejecutar la aplicación, con el cambio anterior, el mensaje de registro ahora tiene el formato 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}"
  }
}

Sugerencia

El Json formateador de consola, de forma predeterminada, registra cada mensaje en una sola línea. Para que sea más legible al configurar el formato, establezca JsonWriterOptions.Indented a true.

Precaución

Al usar el formateador de consola Json, no pase mensajes de registro que ya se hayan serializado como JSON. La propia infraestructura de registro ya administra la serialización de los mensajes de registro, por lo que si va a pasar un mensaje de registro que ya está serializado, se serializará doblemente, lo que provocará una salida con formato incorrecto.

Definición del formateador con configuración

En los ejemplos anteriores se ha mostrado cómo registrar un formateador mediante programación. Como alternativa, puede hacerlo con la configuración. Tenga en cuenta el código fuente de ejemplo de aplicación web anterior, si actualiza el archivo appsettings.json en lugar de llamar ConfigureLogging al archivo Program.cs , podría obtener el mismo resultado. El archivo actualizado appsettings.json configuraría el formateador de la siguiente manera:

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

Los dos valores de clave que deben establecerse son "FormatterName" y "FormatterOptions". Si un formateador con el valor establecido para "FormatterName" ya está registrado, se selecciona ese formateador y sus propiedades se pueden configurar siempre y cuando se proporcionen como una clave dentro del "FormatterOptions" nodo. Los nombres de formateador predefinidos se reservan en ConsoleFormatterNames:

Implementación de un formateador personalizado

Para implementar un formateador personalizado, necesita:

Cree un método de extensión para controlar esto automáticamente:

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 Se definen de la siguiente manera:

using Microsoft.Extensions.Logging.Console;

namespace Console.ExampleFormatters.Custom;

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

En el código anterior, las opciones son una subclase de ConsoleFormatterOptions.

La AddConsoleFormatter API:

  • Registra una subclase de ConsoleFormatter
  • Controla la configuración:
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.");
}

Defina una CustomFormatter subclase de ConsoleFormatter:

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

namespace Console.ExampleFormatters.Custom;

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

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

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

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

        if (message is null)
        {
            return;
        }

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

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

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

La API anterior CustomFormatter.Write<TState> determina qué texto se envuelve alrededor de cada mensaje de log. Un estándar ConsoleFormatter debe ser capaz de ajustar en torno a los ámbitos, las marcas de tiempo y el nivel de gravedad de los registros, como mínimo. Además, puede codificar colores ANSI en los mensajes de registro y proporcionar también indentaciones deseadas. La implementación de CustomFormatter.Write<TState> carece de estas capacidades.

Para obtener inspiración sobre la personalización adicional del formato, consulte las implementaciones existentes en el Microsoft.Extensions.Logging.Console espacio de nombres:

Opciones de configuración personalizadas

Para personalizar aún más la extensibilidad del registro, la clase derivada ConsoleFormatterOptions se puede configurar desde cualquier proveedor de configuración. Por ejemplo, podría usar el proveedor de configuración JSON para definir las opciones personalizadas. En primer lugar, defina la ConsoleFormatterOptions subclase.

using Microsoft.Extensions.Logging.Console;

namespace Console.ExampleFormatters.CustomWithConfig;

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

    public string? CustomSuffix { get; set; }
}

La clase de opciones de formateador de consola anterior define dos propiedades personalizadas, que representan un prefijo y un sufijo. A continuación, defina el archivo appsettings.json que configurará las opciones del formateador de consola.

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

En el archivo de configuración JSON anterior:

  • El "Logging" nodo define un "Console".
  • El nodo "Console" especifica un objeto "FormatterName" de tipo "CustomTimePrefixingFormatter", que se asigna a un formateador personalizado.
  • El "FormatterOptions" nodo define un "CustomPrefix", y "CustomSuffix", así como otras opciones derivadas.

Sugerencia

La ruta JSON $.Logging.Console.FormatterOptions está reservada y se asignará a un objeto ConsoleFormatterOptions personalizado cuando se agregue mediante el método de extensión AddConsoleFormatter. Esto proporciona la capacidad de definir propiedades personalizadas, además de las disponibles.

Observe la sintaxis CustomDatePrefixingFormatter siguiente:

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

En la implementación del formateador anterior:

Para usar opciones de configuración personalizadas, con implementaciones de formateadores personalizados, agréguelas al llamar a 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.");
}

La siguiente salida de la consola es similar a la que podría ver al usar este objeto CustomTimePrefixingFormatter.

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

Implementación del formato de color personalizado

Para habilitar correctamente las funcionalidades de color en su formateador de registro personalizado, puede extender el SimpleConsoleFormatterOptions, ya que tiene la propiedad SimpleConsoleFormatterOptions.ColorBehavior, que puede ser útil para habilitar los colores en los registros.

Cree un CustomColorOptions que derive de SimpleConsoleFormatterOptions.

using Microsoft.Extensions.Logging.Console;

namespace Console.ExampleFormatters.Custom;

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

A continuación, escriba algunos métodos de extensión en una TextWriterExtensions clase que permita insertar convenientemente colores codificados ANSI en mensajes de registro con formato:

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

Un formateador de color personalizado que controla la aplicación de colores personalizados podría definirse de la siguiente manera:

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

Al ejecutar la aplicación, los registros mostrarán el CustomPrefix mensaje en el color verde cuando FormatterOptions.ColorBehavior sea Enabled.

Nota:

Cuando LoggerColorBehavior es Disabled, los mensajes de registro no interpretan códigos de color ANSI insertados en los mensajes de registro. En su lugar, generan el mensaje sin procesar. Por ejemplo, tenga en cuenta lo siguiente:

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

Esto generaría la cadena textual sin color.

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

Consulte también