Logging em aplicações C#: melhores práticas
Logging não é apenas registrar mensagens em um arquivo. Em aplicações .NET modernas, é uma ferramenta criticamente importante para monitoramento, depuração e auditoria. Um logging configurado corretamente permite encontrar rapidamente as causas de falhas, analisar o desempenho e garantir a conformidade com os requisitos de segurança. Neste artigo, vamos abordar as melhores práticas de logging em C# que ajudarão você a construir um sistema confiável de coleta de informações de diagnóstico.
Escolha da biblioteca de logging: Serilog vs NLog vs ILogger nativo
No .NET, existem várias soluções populares. Vamos analisar seus pontos fortes e fracos.
- Microsoft.Extensions.Logging (ILogger) — interface abstrata nativa. Adequada para projetos simples. Não suporta logging estruturado "pronto para uso".
- Serilog — líder em popularidade. Destaca-se pela facilidade de configuração, suporte poderoso para logs estruturados e um conjunto extenso de sinks (destinos de dados).
- NLog — framework maduro com configuração flexível via XML ou código. Excelente para sistemas legados e cenários complexos de roteamento.
Para um novo projeto, recomenda-se Serilog. Ele se integra facilmente com ILogger e fornece uma API concisa. Exemplo de configuração:
// Instalação: dotnet add package Serilog.AspNetCoreusing Serilog;
Log.Logger = new LoggerConfiguration() .MinimumLevel.Information() .WriteTo.Console() .WriteTo.File("logs/app-.log", rollingInterval: RollingInterval.Day) .CreateLogger();
var builder = WebApplication.CreateBuilder(args);builder.Host.UseSerilog(); // Substituição do logger padrãoUso correto dos níveis de logging
Não misture todas as mensagens em um único nível. Use a seguinte gradação:
- Trace (0) — informações extremamente detalhadas para depuração. Inclui detalhes da execução de cada função. Ative apenas no ambiente de desenvolvimento.
- Debug (1) — dados úteis para o desenvolvedor: valores de variáveis, resultados da execução de métodos.
- Information (2) — eventos de negócio: "Usuário fez login", "Pedido criado". Devem ser compreensíveis não apenas para o programador.
- Warning (3) — anomalias que não interrompem o funcionamento: tempo de execução excedido, tentativas repetidas de conexão.
- Error (4) — exceções e falhas que exigem intervenção. Sempre registre o stack trace completo.
- Critical (5) — erros fatais: perda de conexão com o banco de dados, estouro de memória. Exigem notificação imediata.
Exemplo de logging correto em um controller:
[ApiController][Route("api/orders")]public class OrdersController : ControllerBase{ private readonly ILogger<OrdersController> _logger;
public OrdersController(ILogger<OrdersController> logger) { _logger = logger; }
[HttpPost] public IActionResult CreateOrder(OrderDto order) { _logger.LogInformation("Criação do pedido {OrderId} para o usuário {UserId}", order.Id, order.UserId); try { // lógica de negócio _logger.LogInformation("Pedido {OrderId} criado com sucesso", order.Id); return Ok(); } catch (Exception ex) { _logger.LogError(ex, "Erro ao criar o pedido {OrderId}", order.Id); return StatusCode(500); } }}Logging estruturado e contexto
Evite concatenação de strings nos logs. Em vez de Log.Information("User: " + user.Name), use templates com parâmetros:
_logger.LogInformation("Usuário {UserName} executou