Partilhar via


Formatação do log do console

O Microsoft.Extensions.Logging.Console namespace oferece suporte para formatação personalizada nos registos da consola. Existem três opções de formatação pré-definidas disponíveis: Simple, Systemd, e Json.

Importante

Antes do .NET 5, o ConsoleLoggerFormat enum permitia selecionar o formato de registo desejado, seja legível por humanos, que era o Default, ou linha única, também conhecido como Systemd. No entanto, estes não eram personalizáveis e agora estão obsoletos.

Neste artigo, vai aprender sobre formatadores de logs para consolas. O código-fonte de exemplo demonstra como:

  • Registe um novo formatador.
  • Selecione um formatador registado para usar, seja através de código ou configuração.
  • Implementa um formatador personalizado. Atualiza-se a configuração através IOptionsMonitor<TOptions> e ativa-se a formatação de cor personalizada.

Sugestão

Todo o código-fonte de exemplo de registro está disponível no Navegador de amostras para download. Para obter mais informações, consulte Procurar exemplos de código: fazendo login no .NET.

Formatador de registos

O Console fornecedor de registos tem vários formatadores pré-definidos e expõe a possibilidade de criar o seu próprio formatador personalizado. Para registar qualquer um dos formatadores disponíveis, use o método de extensão correspondente Add{Type}Console :

Tipos disponíveis Método para registar tipo
ConsoleFormatterNames.Json ConsoleLoggerExtensions.AddJsonConsole
ConsoleFormatterNames.Simple ConsoleLoggerExtensions.AddSimpleConsole
ConsoleFormatterNames.Systemd ConsoleLoggerExtensions.AddSystemdConsole

Simple

Para usar o Simple formatador de consola, registe-o com 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.");
}

No código-fonte de exemplo anterior, o ConsoleFormatterNames.Simple formatador estava registado. Fornece aos logs a capacidade não só de envolver informações como hora e nível de log em cada mensagem de log, mas também permite a incorporação de cores ANSI e a indentação de mensagens.

Quando esta aplicação de exemplo é executada, as mensagens de registo são formatadas conforme mostrado abaixo:

Registos de consola de exemplo escritos com o formatador simples.

Systemd

O ConsoleFormatterNames.Systemd logger da consola:

  • Utiliza o formato de nível de log "Syslog" e as severidades.
  • Não formata mensagens com cores.
  • Regista sempre as mensagens numa única linha.

Isto é geralmente útil para contentores, que frequentemente utilizam registos Systemd em consolas. O Simple logger de consola também permite uma versão compacta que regista uma única linha e permite desativar cores, como mostrado numa amostra 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.");
}

O exemplo produz uma saída semelhante às seguintes mensagens de log:

Registos de consola de exemplo escritos com o formatador Systemd.

Json

Para escrever registos em formato JSON, utiliza-se o Json formatador de consola. O código-fonte de exemplo mostra como uma aplicação ASP.NET Core pode registar essa informação. Usando o webapp modelo, crie uma nova aplicação ASP.NET Core com o novo comando dotnet :

dotnet new webapp -o Console.ExampleFormatters.Json

Ao executar a aplicação, usando o código modelo, obtém o formato de registo predefinido abaixo:

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

Por defeito, o Simple formato de registo da consola é selecionado com a configuração padrão. Muda isto chamando AddJsonConsole no 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();

Alternativamente, pode também configurar isto usando a configuração de registo, como a encontrada no ficheiroappsettings.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": "*"
}

Execute a aplicação novamente, com a alteração acima, a mensagem de registo está agora formatada como 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}"
  }
}

Sugestão

O Json formatador da consola, por defeito, regista cada mensagem numa única linha. Para o tornar mais legível ao configurar o formatador, defina JsonWriterOptions.Indented para true.

Atenção

Ao usar o formatador de consola JSON, não passe mensagens de log que já foram serializadas como JSON. A própria infraestrutura de registo gere a serialização das mensagens de registo. Portanto, se enviares uma mensagem de log que já está serializada, ela será duplicadamente serializada, causando assim uma saída mal formada.

Definir formatador com configuração

As amostras anteriores mostraram como registar um formatador programaticamente. Alternativamente, isto pode ser feito com configuração. Considere o exemplo anterior de código-fonte para a aplicação web: se atualizar o ficheiro appsettings.json em vez de chamar ConfigureLoggingProgram.cs, pode obter o mesmo resultado. O ficheiro atualizado appsettings.json configuraria o formatador da seguinte forma:

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

Os dois valores-chave que precisam de ser definidos são "FormatterName" e "FormatterOptions". Se um formatador com o valor definido para "FormatterName" já estiver registado, será selecionado esse formatador, e as suas propriedades podem ser configuradas desde que sejam fornecidas como chave dentro do nó "FormatterOptions". Os nomes predefinidos do formatador são reservados em ConsoleFormatterNames:

Implementar um formador personalizado

Para implementar um formatador personalizado, precisa de:

Crie um método de extensão para tratar disto por si:

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

São CustomOptions definidos da seguinte forma:

using Microsoft.Extensions.Logging.Console;

namespace Console.ExampleFormatters.Custom;

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

No código anterior, as opções são uma subclasse de ConsoleFormatterOptions.

A AddConsoleFormatter API:

  • Regista uma subclasse de ConsoleFormatter.
  • Gerencia a configuração. Utiliza um token de alteração para sincronizar atualizações, com base no padrão de opções, e na interface IOptionsMonitor .
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 uma CustomFormatter subclasse 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();
}

A API anterior CustomFormatter.Write<TState> dita que texto é enrolado em torno de cada mensagem de log. Um ConsoleFormatter deve ser capaz de envolver no mínimo os escopos, etiquetas de tempo e o nível de severidade dos registos. Além disso, pode codificar as cores ANSI nas mensagens de registo e fornecer também as indentações desejadas. A implementação do CustomFormatter.Write<TState> carece destas capacidades.

Para inspiração na personalização adicional da formatação, veja as implementações existentes no Microsoft.Extensions.Logging.Console namespace:

Opções de configuração personalizadas

Para personalizar ainda mais a extensibilidade do registo, a sua classe derivada ConsoleFormatterOptions pode ser configurada a partir de qualquer fornecedor de configuração. Por exemplo, pode usar o fornecedor de configuração JSON para definir as suas opções personalizadas. Primeiro, defina a sua ConsoleFormatterOptions subclasse.

using Microsoft.Extensions.Logging.Console;

namespace Console.ExampleFormatters.CustomWithConfig;

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

    public string? CustomSuffix { get; set; }
}

A classe de opções de formatador de consola anterior define duas propriedades personalizadas, representando um prefixo e um sufixo. De seguida, defina o ficheiroappsettings.json que irá configurar as opções de formateador da sua 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": "*"
}

No ficheiro de configuração JSON anterior:

  • O "Logging" nó define um "Console".
  • O nó "Console" especifica um "FormatterName" de "CustomTimePrefixingFormatter", que mapeia para um formatador personalizado.
  • O nó "FormatterOptions" define um "CustomPrefix", um "CustomSuffix" e algumas outras opções derivadas.

Sugestão

O $.Logging.Console.FormatterOptions caminho JSON é reservado e será mapeado para um ConsoleFormatterOptions personalizado quando adicionado usando o método extensor AddConsoleFormatter. Isto permite definir propriedades personalizadas, para além das disponíveis.

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

Na implementação anterior do formatador:

Para usar opções de configuração personalizadas, adicione implementações de formateadores personalizados ao chamar 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 saída seguinte da consola é semelhante ao que se poderia esperar ao usar este CustomTimePrefixingFormatter.

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

Implementar formatação de cor personalizada

Para ativar corretamente as capacidades de cor no seu formatador de registo de logs personalizado, pode estender a classe SimpleConsoleFormatterOptions, pois tem uma propriedade SimpleConsoleFormatterOptions.ColorBehavior que pode ser útil para ativar cores nos registos.

Crie um CustomColorOptions que deriva de SimpleConsoleFormatterOptions:

using Microsoft.Extensions.Logging.Console;

namespace Console.ExampleFormatters.Custom;

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

De seguida, escreva alguns métodos de extensão numa TextWriterExtensions classe que permitam incorporar convenientemente cores codificadas ANSI em mensagens de registo formatadas:

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

Um formatador de cor personalizado que gere a aplicação de cores pode ser definido da seguinte forma:

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

Quando executa a aplicação, os registos mostram a CustomPrefix mensagem na cor verde quando FormatterOptions.ColorBehavior é Enabled.

Observação

Quando LoggerColorBehavior é Disabled, as mensagens log não interpretam códigos de cor ANSI incorporados dentro das mensagens log. Em vez disso, apresentam a mensagem bruta. Por exemplo, considere o seguinte:

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

Isto geraria a sequência literal, e ela não está colorizada.

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

Consulte também