Formatação de log de console
No .NET 5, o suporte para formatação personalizada foi adicionado aos logs de console no namespace Microsoft.Extensions.Logging.Console
. Há três opções de formatação predefinidas disponíveis: Simple
, Systemd
e Json
.
Importante
Antes, a enumeração ConsoleLoggerFormat era permitida para selecionar o formato de log desejado, seja o legível por pessoas, que era o Default
ou o de linha única, também conhecido como Systemd
. No entanto, eles não eram personalizáveis e agora foram preteridos.
Neste artigo, você conhecerá os formatadores de log do console. O código-fonte de exemplo demonstra como:
- Registrar um novo formatador
- Selecionar um formatador registrado a ser usado
- Por meio do código ou da configuração
- Implementar um formatador personalizado
- Atualizar a configuração por meio de IOptionsMonitor<TOptions>
- Habilitar a formatação de cores personalizadas
Dica
Todo o código-fonte do exemplo de log está disponível no Navegador de Exemplos para download. Para obter mais informações, confira Procurar exemplos de código: log no .NET.
Registrar o formatador
O provedor de log Console
tem vários formatadores predefinidos e expõe a capacidade de criar o próprio formatador personalizado. Para registrar um dos formatadores disponíveis, use o método de extensão correspondente Add{Type}Console
:
Tipos disponíveis | Método para registrar o tipo |
---|---|
ConsoleFormatterNames.Json | ConsoleLoggerExtensions.AddJsonConsole |
ConsoleFormatterNames.Simple | ConsoleLoggerExtensions.AddSimpleConsole |
ConsoleFormatterNames.Systemd | ConsoleLoggerExtensions.AddSystemdConsole |
Simples
Para usar o formatador de console Simple
, registre-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 formatador ConsoleFormatterNames.Simple foi registrado. Ele fornece logs com a capacidade de não apenas encapsular informações, como tempo e nível de log em cada mensagem de log, mas também permite a inserção de cores ANSI e recuo de mensagens.
Quando este aplicativo de exemplo é executado, as mensagens de log são formatadas, conforme mostrado abaixo:
Systemd
O agente de console ConsoleFormatterNames.Systemd:
- Usa o formato e as severidades do nível de log "Syslog"
- Não formata mensagens com cores
- Sempre registra mensagens em uma só linha
Isso geralmente é útil para contêineres, que geralmente usam o log de console Systemd
. Com o .NET 5, o agente de console Simple
também habilita uma versão compacta que faz logon em uma só linha e também permite desabilitar cores, conforme mostrado em um exemplo 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:
Json
Para gravar logs em um formato JSON, o formatador de console Json
é usado. O código-fonte de exemplo mostra como um aplicativo ASP.NET Core pode registrá-lo. Usando o modelo webapp
, crie um aplicativo ASP.NET Core com o comando dotnet new:
dotnet new webapp -o Console.ExampleFormatters.Json
Ao executar o aplicativo, usando o código do modelo, você obtém o formato de log padrão 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 padrão, o formatador de log de console Simple
é selecionado com a configuração padrão. Altere isso 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();
Como alternativa, você também pode configurar isso usando a configuração de log, como a encontrada no arquivo 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": "*"
}
Execute o aplicativo novamente, com a alteração acima, a mensagem de log agora está 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}"
}
}
Dica
O formatador de console Json
, por padrão, registra cada mensagem em uma só linha. Para torná-lo mais legível ao configurar o formatador, defina JsonWriterOptions.Indented como true
.
Cuidado
Ao usar o formatador de console JSON, não passe mensagens de log que já foram serializadas como JSON. A própria infraestrutura de log já gerencia a serialização de mensagens de log, portanto, se você quiser passar uma mensagem de log que já esteja serializada, ela será serializada duas vezes, causando uma saída malformada.
Definir o formatador com configuração
Os exemplos anteriores mostraram como registrar um formatador programaticamente. Como alternativa, isso pode ser feito com uma configuração. Considere o código-fonte de exemplo do aplicativo Web anterior. Se você atualizar o arquivo appsettings.json em vez de chamar ConfigureLogging
no arquivo Program.cs , poderá obter o mesmo resultado. O arquivo appsettings.json
atualizado configuraria o formatador da seguinte maneira:
{
"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 de chave que precisam ser definidos são "FormatterName"
e "FormatterOptions"
. Se um formatador com o valor definido para "FormatterName"
já estiver registrado, esse formatador será selecionado e suas propriedades poderão ser configuradas desde que sejam fornecidas como uma chave dentro do nó "FormatterOptions"
. Os nomes de formatador predefinidos são reservados em ConsoleFormatterNames:
Implementar um formatador personalizado
Para implementar um formatador personalizado, você precisa:
- Criar uma subclasse de ConsoleFormatter, que representa o formatador personalizado
- Registrar o formatador personalizado com
Crie um método de extensão para lidar com isso:
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);
}
As CustomOptions
são definidas desta 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 API AddConsoleFormatter
:
- Registra uma subclasse de
ConsoleFormatter
- Manipula a configuração:
- Usa 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.");
}
Definir uma subclasse de CustomFormatter
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 CustomFormatter.Write<TState>
anterior determina qual texto é encapsulado em cada mensagem de log. Um ConsoleFormatter
padrão deve ter a capacidade mínima de encapsular escopos, carimbos de data/hora e o nível de severidade dos logs. Além disso, você também pode codificar cores ANSI nas mensagens de log e fornecer os recuos desejados. A implementação do CustomFormatter.Write<TState>
não tem essas funcionalidades.
Para se inspirar em personalizar ainda mais a formatação, confira as implementações existentes no namespace Microsoft.Extensions.Logging.Console
:
Opções de configuração personalizada
Para personalizar ainda mais a extensibilidade de log, a classe derivada ConsoleFormatterOptions pode ser configurada por meio de qualquer provedor de configuração. Por exemplo, você pode usar o provedor de configuração JSON para definir as opções personalizadas. Primeiro defina a subclasse 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; }
}
A classe de opções de formatador de console anterior define duas propriedades personalizadas, representando um prefixo e um sufixo. Depois, defina o arquivo appsettings.json que vai configurar as opções de formatador do console.
{
"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 arquivo de configuração JSON anterior:
- O nó
"Logging"
define um"Console"
. - O nó
"Console"
especifica um"FormatterName"
de"CustomTimePrefixingFormatter"
, que é mapeado para um formatador personalizado. - O nó
"FormatterOptions"
define um"CustomPrefix"
e"CustomSuffix"
, bem como algumas outras opções derivadas.
Dica
O caminho JSON $.Logging.Console.FormatterOptions
é reservado e é mapeado para um ConsoleFormatterOptions personalizado quando adicionado usando o método de extensão AddConsoleFormatter. Isso fornece a capacidade de definir propriedades personalizadas, além das disponíveis.
Considere o seguinte 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 do formatador anterior:
- As
CustomWrappingConsoleFormatterOptions
são monitoradas quanto à alteração e atualizadas corretamente. - As mensagens gravadas são encapsuladas com o prefixo e o sufixo configurados.
- Um carimbo de data/hora é adicionado após o prefixo, mas antes da mensagem usando os valores configurados ConsoleFormatterOptions.UseUtcTimestamp e ConsoleFormatterOptions.TimestampFormat.
Para usar opções de configuração personalizadas, com implementações de formatador personalizado, adicione 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 do console a seguir é semelhante à esperada quando esse CustomTimePrefixingFormatter
é usado.
|-<[ 15:03:15.6179 Hello World! ]>-|
|-<[ 15:03:15.6347 The .NET developer community happily welcomes you. ]>-|
Implementar a formatação de cores personalizadas
Para habilitar corretamente as funcionalidades de cor no formatador de log personalizado, estenda o SimpleConsoleFormatterOptions como ele tivesse uma propriedade SimpleConsoleFormatterOptions.ColorBehavior que pode ser útil para habilitar cores em logs.
Crie uma classe SimpleConsoleFormatterOptions
derivada de CustomColorOptions
:
using Microsoft.Extensions.Logging.Console;
namespace Console.ExampleFormatters.Custom;
public class CustomColorOptions : SimpleConsoleFormatterOptions
{
public string? CustomPrefix { get; set; }
}
Depois, escreva alguns métodos de extensão em uma classe TextWriterExtensions
que permitam inserir facilmente as cores codificadas como ANSI em mensagens de log 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 cores personalizadas que aplica cores personalizadas pode ser definido da seguinte maneira:
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 você executar o aplicativo, os logs mostrarão a mensagem CustomPrefix
na cor verde quando FormatterOptions.ColorBehavior
for Enabled
.
Observação
Quando LoggerColorBehavior é Disabled
, as mensagens de log não interpretam códigos de cor ANSI inseridos em mensagens de log. Nesse caso, a mensagem bruta é gerada. Considere o seguinte exemplo:
logger.LogInformation("Random log \x1B[42mwith green background\x1B[49m message");
Isso geraria a cadeia de caracteres verbatim não colorida.
Random log \x1B[42mwith green background\x1B[49m message