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.
Como autor de uma biblioteca, disponibilizar logs é uma ótima maneira de fornecer aos consumidores informações sobre o funcionamento interno da sua biblioteca. Esta orientação ajuda você a expor o registro em log de forma consistente com outras bibliotecas e estruturas do .NET. Também ajuda a evitar gargalos de desempenho comuns que podem não ser óbvios de outra forma.
Quando usar a ILoggerFactory interface
Ao escrever uma biblioteca que emite logs, você precisa de um ILogger objeto para registrar os logs. Para obter esse objeto, sua API pode aceitar um ILogger<TCategoryName> parâmetro ou pode aceitar um ILoggerFactory após o qual você chama ILoggerFactory.CreateLogger. Que abordagem deve ser preferida?
Quando precisar de um objeto de registo de logs que possa ser partilhado com várias classes para que todas elas possam gerar logs, use
ILoggerFactory. É recomendável que cada classe crie logs com uma categoria separada, com o mesmo nome da classe. Para fazer isso, você precisa que a fábrica crie objetos exclusivosILogger<TCategoryName>para cada classe que emite logs. Exemplos comuns incluem APIs de ponto de entrada público para uma biblioteca ou construtores públicos de tipos que podem criar classes auxiliares internamente.Quando você precisar de um objeto de log que seja usado apenas dentro de uma classe e nunca compartilhado, use
ILogger<TCategoryName>, ondeTCategoryNameé o tipo que produz os logs. Um exemplo comum disso é um construtor para uma classe criada por injeção de dependência.
Se você estiver projetando uma API pública que deve permanecer estável ao longo do tempo, lembre-se de que talvez deseje refatorar sua implementação interna no futuro. Mesmo que uma classe não crie nenhum tipo auxiliar interno inicialmente, isso pode mudar à medida que o código evolui. O uso ILoggerFactory acomoda a criação de novos ILogger<TCategoryName> objetos para quaisquer novas classes sem alterar a API pública.
Para obter mais informações, consulte Como as regras de filtragem são aplicadas.
Prefira o registro em log gerado pelo código-fonte
A ILogger API suporta duas abordagens para usar a API. Você pode chamar métodos como LoggerExtensions.LogError e LoggerExtensions.LogInformation, ou pode usar o gerador de fonte de registo para definir métodos de registo fortemente tipados. Para a maioria das situações, o gerador de origem é recomendado porque oferece desempenho superior e digitação mais forte. Ele também isola questões específicas relacionadas ao registo, como modelos de mensagem, IDs e níveis de registo do código chamador. A abordagem não gerada pelo código-fonte é útil principalmente para cenários em que você está disposto a abrir mão dessas vantagens para tornar o código mais conciso.
using Microsoft.Extensions.Logging;
namespace Logging.LibraryAuthors;
internal static partial class LogMessages
{
[LoggerMessage(
Message = "Sold {Quantity} of {Description}",
Level = LogLevel.Information)]
internal static partial void LogProductSaleDetails(
this ILogger logger,
int quantity,
string description);
}
O código anterior:
- Define um
partial classdenominadoLogMessages, que éstaticpara ser utilizado para definir métodos de extensão no tipoILogger. - Decora um
LogProductSaleDetailsmétodo de extensão com oLoggerMessageatributo e oMessagemodelo. - Declara
LogProductSaleDetails, que estende oILoggere aceita aquantityedescription.
Sugestão
Você pode entrar no código gerado a partir do fonte durante a depuração, porque ele faz parte da mesma assemblagem que o código que o chama.
Use IsEnabled para evitar a avaliação dispendiosa de parâmetros
Pode haver situações em que a avaliação de parâmetros é cara. Expandindo o exemplo anterior, imagine que o description parâmetro é um string que é caro de calcular. Talvez o produto que está sendo vendido obtenha uma descrição amigável do produto e dependa de uma consulta de banco de dados ou leitura de um arquivo. Nessas situações, pode instruir o gerador de código-fonte a ignorar o IsEnabled protetor e adicionar manualmente o IsEnabled protetor no ponto de chamada. Isso permite que o usuário determine onde o protetor é chamado e garante que os parâmetros que podem ser caros para calcular sejam avaliados apenas quando realmente necessário. Considere o seguinte código:
using Microsoft.Extensions.Logging;
namespace Logging.LibraryAuthors;
internal static partial class LogMessages
{
[LoggerMessage(
Message = "Sold {Quantity} of {Description}",
Level = LogLevel.Information,
SkipEnabledCheck = true)]
internal static partial void LogProductSaleDetails(
this ILogger logger,
int quantity,
string description);
}
Quando o método de LogProductSaleDetails extensão é chamado, o protetor IsEnabled é invocado manualmente e a avaliação de parâmetros com custo elevado é realizada apenas quando necessário. Considere o seguinte código:
if (_logger.IsEnabled(LogLevel.Information))
{
// Expensive parameter evaluation
var description = product.GetFriendlyProductDescription();
_logger.LogProductSaleDetails(
quantity,
description);
}
Para obter mais informações, consulte Geração de origem de log em tempo de compilação e Log de alto desempenho no .NET.
Evite a interpolação de cadeias de caracteres no log
Um erro comum é usar a interpolação de cadeia de caracteres para criar mensagens de log. A interpolação de cadeia de caracteres no log é problemática para o desempenho, pois a cadeia de caracteres é avaliada mesmo que a correspondente LogLevel não esteja habilitada. Em vez de interpolação de cadeia de caracteres, use o modelo de mensagem de log, formatação e lista de argumentos. Para obter mais informações, consulte Fazendo login no .NET: modelo de mensagem de log.
Usar definições padrão de registo no-op
Pode haver momentos, ao consumir uma biblioteca que expõe APIs de log que esperam um ILogger ou ILoggerFactory, que você não deseja fornecer um registrador. Nesses casos, o pacote Microsoft.Extensions.Logging.Abstractions NuGet fornece valores padrão para no-op de registo.
Os utilizadores de biblioteca podem usar por defeito o log nulo caso nenhum ILoggerFactory seja fornecido. O uso de registro nulo difere da definição de tipos como anuláveis (ILoggerFactory?), uma vez que os tipos não são nulos. Esses tipos por conveniência não registam nada e são essencialmente operações nulas. Considere a utilização de qualquer um dos tipos de abstração disponíveis, quando aplicável: