Registro em aplicações C#: melhores práticas e ferramentas (.NET)
Registro (logging) não é apenas gravar mensagens em um arquivo. É um componente essencial de qualquer aplicação de produção em C#. Sem um sistema de registro de qualidade, você trabalha às cegas: erros passam despercebidos, o desempenho é difícil de analisar e a depuração se torna um jogo de adivinhação. Neste artigo, abordaremos as melhores práticas de registro no ecossistema .NET, exploraremos bibliotecas populares (Serilog, NLog), os níveis de registro corretos e uma abordagem estruturada para coleta de dados.
1. Escolha da biblioteca de registro: Serilog vs NLog
No mundo .NET, existem várias soluções maduras. As duas mais populares são Serilog e NLog. Ambas suportam registro assíncrono, múltiplos sinks (destinos de saída) e integração com .NET Core/5+ através de ILogger.
Serilog
Serilog é conhecido por sua filosofia de registro estruturado. Em vez de strings simples, você passa objetos, e o Serilog os serializa em JSON. Isso é ideal para sistemas como Elasticsearch, Seq ou Datadog.
// Exemplo Serilogusing Serilog;
Log.Logger = new LoggerConfiguration() .MinimumLevel.Information() .WriteTo.Console() .WriteTo.File("logs/app-.log", rollingInterval: RollingInterval.Day) .CreateLogger();
Log.Information("Usuário {UserId} fez login em {Time}", userId, DateTime.UtcNow);NLog
NLog é uma ferramenta mais tradicional, mas não menos poderosa. É excelente para projetos que precisam de configuração flexível via XML ou código. Suporta rotação de arquivos, envio por email e integração com bancos de dados.
// Exemplo NLogusing NLog;
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
Logger.Info("Usuário {UserId} executou uma ação", userId);Quando escolher o quê? Se você está construindo microsserviços ou usando a stack ELK — escolha Serilog. Se você precisa de uma configuração simples em projetos legados — NLog. De qualquer forma, ambos suportam o ILogger padrão do Microsoft.Extensions.Logging.
2. Níveis de registro: quando e o que registrar
Um dos erros mais comuns é registrar tudo no nível Information ou, ao contrário, colocar Debug em todos os lugares. Use os níveis corretos:
- Trace (0) — informação extremamente detalhada: entrada/saída de métodos, valores de variáveis. Usado apenas durante a depuração.
- Debug (1) — mensagens de depuração, úteis para o desenvolvedor, mas não para o operador.
- Information (2) — eventos de negócio: "pedido criado", "usuário registrado". Este é o nível de trabalho principal.
- Warning (3) — situação anormal que não quebra a aplicação: timeout de requisição, nova tentativa de conexão.
- Error (4) — exceções tratadas, erros de lógica de negócio, falhas na operação de um módulo.
- Critical (5) — erros fatais: perda de conexão com o banco de dados, falta de memória, falha de toda a aplicação.
// Exemplo de uso correto dos níveispublic async Task<Order> CreateOrderAsync(CreateOrderRequest request){ Log.Debug("Início da criação do pedido para o usuário {UserId}", request.UserId);
try { var order = new Order(request); await _repository.SaveAsync(order); Log.Information("Pedido {OrderId} criado pelo usuário {UserId}", order.Id, request.UserId); return order; } catch (DbException ex) { Log.Error(ex, "Erro de BD ao criar pedido para o usuário {UserId}", request.UserId); throw; // Propaga para cima }}3. Registro estruturado: por que é importante?
O registro tradicional através de st