Registro en aplicaciones C#: mejores prácticas en la práctica
El registro no es solo escribir mensajes en un archivo. Es una herramienta esencial para la monitorización, depuración y auditoría de cualquier aplicación de producción en C#. Un registro correctamente configurado permite encontrar rápidamente las causas de fallos, analizar el comportamiento del sistema y prevenir incidentes. En este artículo, analizaremos las mejores prácticas de registro en .NET que podrá aplicar de inmediato en sus proyectos.
1. Elección de la biblioteca: Serilog vs NLog vs ILogger integrado
En el .NET moderno existen tres enfoques principales para el registro. Analicemos sus puntos fuertes.
- ILogger integrado (Microsoft.Extensions.Logging) — una interfaz abstracta básica. Está integrado en ASP.NET Core y es mínimamente configurable. Es adecuado para proyectos simples, pero requiere proveedores externos para escenarios avanzados.
- Serilog — el estándar de facto en la industria. Admite registro estructurado "de fábrica", un rico ecosistema de sinks (destinos) y una configuración sencilla a través de la configuración.
- NLog — un framework maduro con enrutamiento flexible y soporte para sistemas heredados. Se destaca por su alto rendimiento y configuración detallada de reglas.
Recomendación: para proyectos nuevos, use Serilog — se integra mejor con las prácticas modernas (ELK, Application Insights). Para sistemas de alta carga donde el rendimiento es crítico, considere NLog.
// Ejemplo de configuración mínima de Serilog en Program.csusing Serilog;
Log.Logger = new LoggerConfiguration() .MinimumLevel.Information() .WriteTo.Console() .WriteTo.File("logs/app-.log", rollingInterval: RollingInterval.Day) .CreateLogger();
try{ Log.Information("Aplicación iniciada"); // su código}catch (Exception ex){ Log.Fatal(ex, "Error crítico al iniciar");}finally{ Log.CloseAndFlush();}2. Niveles de registro: cuándo y qué escribir
La elección incorrecta del nivel de registro es uno de los errores más comunes. Analicemos cada nivel y su propósito.
- Trace / Verbose — solo para depuración por parte del desarrollador. Nunca lo active en producción a menos que sea absolutamente necesario.
- Debug — información de diagnóstico para el desarrollo. Puede activarse temporalmente para buscar un problema.
- Information — funcionamiento normal de la aplicación: solicitudes, operaciones exitosas, eventos de negocio. Nivel principal en producción.
- Warning — problema potencial: poco espacio disponible, reintentos, API obsoleta.
- Error — excepciones y fallos que la aplicación ha manejado, pero el usuario ha notado el problema.
- Fatal / Critical — errores irrecuperables que requieren intervención inmediata del administrador.
// Ejemplo de uso correcto de nivelespublic class OrderService{ private readonly ILogger<OrderService> _logger;
public OrderService(ILogger<OrderService> logger) { _logger = logger; }
public async Task<Order> CreateOrderAsync(CreateOrderRequest request) { _logger.LogInformation("Creando pedido para el usuario {UserId}", request.UserId);
try { var order = await _repository.SaveAsync(request); _logger.LogInformation("Pedido {OrderId} creado exitosamente", order.Id); return order; } catch (Exception ex) { _logger.LogError(ex, "Error al crear pedido para el usuario {UserId}", request.UserId); throw; } }}3. Registro estructurado: por qué es importante
El registro textual tradicional (a trav