Nota
O acesso a esta página requer autorização. Podes tentar iniciar sessão ou mudar de diretório.
O acesso a esta página requer autorização. Podes tentar mudar de diretório.
Há muitos provedores de registo de logs disponíveis para necessidades comuns de registo. Mas pode ser necessário implementar uma solução personalizada ILoggerProvider quando um dos provedores disponíveis não se adequar às necessidades da sua aplicação. Neste artigo, aprende como implementar um fornecedor de registos personalizado que pode ser usado para colorir registos na consola.
Sugestão
O código fonte de exemplo do fornecedor de registos personalizados está disponível no repositório docs do GitHub.
Exemplo de configuração de logger personalizado
O logger de exemplo cria diferentes entradas de cor na consola por nível de registo e ID de evento usando o seguinte tipo de configuração:
using Microsoft.Extensions.Logging;
public sealed class ColorConsoleLoggerConfiguration
{
public int EventId { get; set; }
public Dictionary<LogLevel, ConsoleColor> LogLevelToColorMap { get; set; } = new()
{
[LogLevel.Information] = ConsoleColor.Green
};
}
O código anterior define a cor padrão do Information nível para Green. O EventId é implicitamente 0.
Criar o registador personalizado
O seguinte excerto de código mostra a ILogger implementação:
using Microsoft.Extensions.Logging;
public sealed class ColorConsoleLogger(
string name,
Func<ColorConsoleLoggerConfiguration> getCurrentConfig) : ILogger
{
public IDisposable? BeginScope<TState>(TState state)
where TState : notnull => default!;
public bool IsEnabled(LogLevel logLevel) =>
getCurrentConfig().LogLevelToColorMap.ContainsKey(logLevel);
public void Log<TState>(
LogLevel logLevel,
EventId eventId,
TState state,
Exception? exception,
Func<TState, Exception?, string> formatter)
{
if (!IsEnabled(logLevel))
{
return;
}
ColorConsoleLoggerConfiguration config = getCurrentConfig();
if (config.EventId == 0 || config.EventId == eventId.Id)
{
ConsoleColor originalColor = Console.ForegroundColor;
Console.ForegroundColor = config.LogLevelToColorMap[logLevel];
Console.WriteLine($"[{eventId.Id,2}: {logLevel,-12}]");
Console.ForegroundColor = originalColor;
Console.Write($" {name} - ");
Console.ForegroundColor = config.LogLevelToColorMap[logLevel];
Console.Write($"{formatter(state, exception)}");
Console.ForegroundColor = originalColor;
Console.WriteLine();
}
}
}
Cada instância do logger é instanciada passando um nome de categoria, que é tipicamente o tipo onde o logger é criado. O IsEnabled método verifica getCurrentConfig().LogLevelToColorMap.ContainsKey(logLevel) se o nível de log solicitado está ativado (ou seja, no dicionário de níveis de log da configuração).
É uma boa prática chamar ILogger.IsEnabled nas implementações de ILogger.Log, uma vez que Log pode ser chamado por qualquer consumidor, e não há garantias de que tenha sido previamente verificado. O método IsEnabled deve ser muito rápido na maioria das implementações.
if (!IsEnabled(logLevel))
{
return;
}
O logger é instanciado com o name e uma Func<ColorConsoleLoggerConfiguration> que retorna a configuração atual.
Importante
A implementação ILogger.Log verifica se o valor config.EventId está definido. Quando config.EventId não está definido ou quando corresponde ao logEntry.EventIdexato, o registador regista a cores.
Provedor de registro personalizado
O objeto ILoggerProvider é responsável pela criação de instâncias do registrador. Não é necessário criar uma instância de logger por categoria, mas faz sentido para alguns loggers, como NLog ou log4net. Essa estratégia permite que você escolha diferentes destinos de saída de log por categoria, como no exemplo a seguir:
using System.Collections.Concurrent;
using System.Runtime.Versioning;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
[UnsupportedOSPlatform("browser")]
[ProviderAlias("ColorConsole")]
public sealed class ColorConsoleLoggerProvider : ILoggerProvider
{
private readonly IDisposable? _onChangeToken;
private ColorConsoleLoggerConfiguration _currentConfig;
private readonly ConcurrentDictionary<string, ColorConsoleLogger> _loggers =
new(StringComparer.OrdinalIgnoreCase);
public ColorConsoleLoggerProvider(
IOptionsMonitor<ColorConsoleLoggerConfiguration> config)
{
_currentConfig = config.CurrentValue;
_onChangeToken = config.OnChange(updatedConfig => _currentConfig = updatedConfig);
}
public ILogger CreateLogger(string categoryName) =>
_loggers.GetOrAdd(categoryName, name => new ColorConsoleLogger(name, GetCurrentConfig));
private ColorConsoleLoggerConfiguration GetCurrentConfig() => _currentConfig;
public void Dispose()
{
_loggers.Clear();
_onChangeToken?.Dispose();
}
}
No código anterior, CreateLogger(String) cria uma única instância do nome ColorConsoleLogger por categoria e a armazena no ConcurrentDictionary<TKey,TValue>.
A ColorConsoleLoggerProvider classe é decorada com duas características:
[UnsupportedOSPlatform("browser")]
[ProviderAlias("ColorConsole")]
public sealed class ColorConsoleLoggerProvider : ILoggerProvider
-
UnsupportedOSPlatformAttribute: O tipo
ColorConsoleLoggernão é suportado no"browser". -
ProviderAliasAttribute: As seções de configuração podem definir opções usando a chave
"ColorConsole".
A configuração pode ser especificada com qualquer provedor válido de configuração de . Considere o seguinte arquivo appsettings.json :
{
"Logging": {
"ColorConsole": {
"LogLevelToColorMap": {
"Information": "DarkGreen",
"Warning": "Cyan",
"Error": "Red"
}
}
}
}
O ficheiro appsettings.json especifica que a cor para o Information nível de log é DarkGreen, o que sobrepõe o valor padrão definido no ColorConsoleLoggerConfiguration objeto.
Utilização e registo do registador personalizado
Por convenção, os serviços são registados para injeção de dependências como parte da rotina de arranque de uma aplicação. Neste exemplo, o serviço de registo é registado diretamente a partir do ficheiro Program.cs .
Para adicionar o fornecedor de registo personalizado e o respetivo logger, adicione um ILoggerProvider invocando o método de extensão personalizado AddColorConsoleLogger no ILoggingBuilder da propriedade IHostApplicationBuilder.Logging.
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Logging.ClearProviders();
builder.Logging.AddColorConsoleLogger(configuration =>
{
// Replace value of "Cyan" from appsettings.json.
configuration.LogLevelToColorMap[LogLevel.Warning]
= ConsoleColor.DarkCyan;
// Replace value of "Red" from appsettings.json.
configuration.LogLevelToColorMap[LogLevel.Error]
= ConsoleColor.DarkRed;
});
using IHost host = builder.Build();
ILogger<Program> logger = host.Services.GetRequiredService<ILogger<Program>>();
logger.LogDebug(1, "Does this line get hit?"); // Not logged
logger.LogInformation(3, "Nothing to see here."); // Logs in ConsoleColor.DarkGreen
logger.LogWarning(5, "Warning... that was odd."); // Logs in ConsoleColor.DarkCyan
logger.LogError(7, "Oops, there was an error."); // Logs in ConsoleColor.DarkRed
logger.LogTrace(5, "== 120."); // Not logged
await host.RunAsync();
Por convenção, os métodos de extensão em ILoggingBuilder são usados para registrar o provedor personalizado:
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Configuration;
public static class ColorConsoleLoggerExtensions
{
public static ILoggingBuilder AddColorConsoleLogger(
this ILoggingBuilder builder)
{
builder.AddConfiguration();
builder.Services.TryAddEnumerable(
ServiceDescriptor.Singleton<ILoggerProvider, ColorConsoleLoggerProvider>());
LoggerProviderOptions.RegisterProviderOptions
<ColorConsoleLoggerConfiguration, ColorConsoleLoggerProvider>(builder.Services);
return builder;
}
public static ILoggingBuilder AddColorConsoleLogger(
this ILoggingBuilder builder,
Action<ColorConsoleLoggerConfiguration> configure)
{
builder.AddColorConsoleLogger();
builder.Services.Configure(configure);
return builder;
}
}
O ILoggingBuilder cria uma ou mais instâncias ILogger. As instâncias ILogger são usadas pela estrutura para registrar as informações.
O código de instância sobrepõe os valores de cor do ficheiroappsettings.json para LogLevel.Warning e LogLevel.Error.
Quando executa esta aplicação simples, ela renderiza uma saída de cor na janela de consola, semelhante à imagem seguinte: