¿Por qué su aplicación C# grita y usted no la escucha?
\nImagine: lanza una nueva versión de un microservicio en C# a medianoche. Todo funciona perfectamente... los primeros 10 minutos. Y luego — ¡pum! — los usuarios se quejan de lentitud, y usted está frente a un archivo de registro de 2 GB tratando de encontrar una aguja en un pajar. ¿Le suena familiar? Si no, o es un genio o nunca ha hecho monitoreo de verdad.
\nEn este artículo, veremos cómo convertir el caos de los registros en un sistema ordenado. Aprenderá a configurar el registro en C# para no volverse loco al hacer deploy, y cómo construir un monitoreo de aplicaciones que realmente ayude, no solo dibuje gráficos bonitos.
\n\nPor dónde empezar: la filosofía del registro correcto
\nMuchos desarrolladores piensan: "Pongo un Console.WriteLine y ya está". Spoiler: no, no está bien. El verdadero registro en C# es el structured logging (registro estructurado). En lugar de cadenas como:
\nLog.Info("User " + userId + " bought item " + itemId);\nEscribe:
\nLog.Information("User {UserId} bought item {ItemId}", userId, itemId);\nLa diferencia es enorme. En el segundo caso, puede filtrar registros por UserId, construir paneles y encontrar problemas rápidamente. Esta es la base del diagnóstico de errores en C# en producción.
Eligiendo la biblioteca: Serilog vs NLog vs log4net
\nEn el ecosistema .NET hay tres actores principales. Comparemos según criterios importantes para un proyecto real:
\n- \n
- Serilog — el favorito del .NET moderno. Ideal para structured logging, fácil de configurar, soporta sinks (salida a archivo, base de datos, Elasticsearch). Lo recomiendo para proyectos nuevos. \n
- NLog — un veterano con configuración flexible mediante XML/JSON. Excelente para sistemas heredados donde ya se usa. \n
- log4net — un clásico que es mejor no tocar a menos que sea estrictamente necesario. El soporte es deficiente, el structured logging requiere parches. \n
Para el trazado .NET en aplicaciones modernas, Serilog es la opción #1. Configurémoslo en 5 minutos.
\n\nConfiguración de Serilog en C#: guía paso a paso
\nInstale los paquetes mediante NuGet:
\ndotnet add package Serilog\ndotnet add package Serilog.Sinks.Console\ndotnet add package Serilog.Sinks.File\ndotnet add package Serilog.Sinks.Seq\nAhora, la configuración mínima en Program.cs para ASP.NET Core:
using Serilog;\n\nLog.Logger = new LoggerConfiguration()\n .MinimumLevel.Information()\n .WriteTo.Console()\n .WriteTo.File("logs/app-.log", rollingInterval: RollingInterval.Day)\n .WriteTo.Seq("http://localhost:5341") // para monitoreo avanzado\n .CreateLogger();\n\ntry\n{\n Log.Information("Starting web application");\n var builder = WebApplication.CreateBuilder(args);\n builder.Host.UseSerilog(); // integración con el host\n // ... resto de la configuración\n var app = builder.Build();\n app.Run();\n}\ncatch (Exception ex)\n{\n Log.Fatal(ex, "Application terminated unexpectedly");\n}\nfinally\n{\n Log.CloseAndFlush();\n}\nObserve el rollingInterval — los registros rotarán cada día, en lugar de crecer indefinidamente. Esta es la base del registro asíncrono en producción.
Registros estructurados: cómo obtener el máximo beneficio
\nSupongamos que tenemos un método de procesamiento de pedidos. Sin estructuración, escribiría:
\nlogger.LogInformation("Processing order {OrderId} for user {UserId}", order.Id, user.Id);\nCon Serilog, esto se convierte en un objeto JSON que se puede analizar. Y si agrega contexto mediante ILogger<T>:
public class OrderService\n{\n private readonly ILogger<OrderService> _logger;\n\n public OrderService(ILogger<OrderService> logger)\n {\n _logger = logge