aspnet-core-logging-ilogger-monitorizacion

Logging en ASP.NET con ILogger

  • 4 min

En .NET, tenemos integrado un sistema de Logging de primer nivel, basado en la interfaz ILogger.

Cuando estamos aprendiendo a programar, nuestra herramienta principal para saber qué pasa es Console.WriteLine("Llegó aquí").

Pero cuando pasamos a una aplicación “real”, usar la consola es una práctica terrible.

  • ❌ No tienes control sobre qué se muestra y qué no (niveles).
  • ❌ No tienes contexto (¿cuándo pasó? ¿en qué hilo?).
  • ❌ No es fácil de buscar ni de exportar a un fichero o base de datos.

Hoy vamos a aprender a dejar mejorar el Logging en nuestra aplicación para que, cuando algo falle en producción, sepamos exactamente por qué.

¿Dónde van los logs?

Por defecto (builder.CreateBuilder), .NET configura:

  • Console: Salida estándar (útil para contenedores/Docker).
  • Debug: Ventana de Output de Visual Studio.
  • EventLog: En Windows (solo si corres en Windows).

Si quieres guardar logs en un fichero de texto, .NET no trae un proveedor nativo para ficheros (curiosamente). Para eso, la industria suele usar librerías de terceros muy famosas como Serilog o NLog, que se integran perfectamente sobre ILogger

La arquitectura de logging

El sistema de logs de .NET se basa en tres pilares:

  1. ILogger (La interfaz): Es lo que usamos en nuestro código para escribir mensajes.
  2. Providers (Los destinos): Son los encargados de “escuchar” esos mensajes y guardarlos. Por defecto, .NET escribe en la Console y en la ventana de Debug de Visual Studio. Pero puedes añadir providers para escribir en archivos, Azure, AWS, ElasticSearch, etc.
  3. Log Levels: Categorizan la importancia del mensaje.

Niveles de Log

No todo lo que ocurre en la app tiene la misma importancia. .NET define 6 niveles estándar. Entenderlos es importante para no saturar tus registros con “ruido”.

NivelMétodoUso
TraceLogTraceDetalles minúsculos. Muchísimo ruido.
(ej: paso a paso de un algoritmo).
DebugLogDebugInformación útil para el desarrollador mientras programa.
InformationLogInformationEl estándar. Cosas que pasan normalmente
(ej: “Usuario registrado”, “Email enviado”).
WarningLogWarningAlgo raro pasó, pero la app se recuperó
(ej: “Reintentando conexión a BBDD”).
ErrorLogErrorFallo. La petición actual falló (ej: “Excepción NullReference”, “BBDD caída”).
CriticalLogCriticalLa aplicación entera está en peligro
(ej: “Disco lleno”, “Memoria agotada”).

Usando ILogger en tu código

Para usar el log, simplemente solicitamos ILogger<T> en el constructor de nuestra clase (o en el endpoint). La T suele ser la propia clase, para saber quién está escribiendo el mensaje.

app.MapGet("/producto/{id}", (int id, ILogger<Program> logger) => 
{
    logger.LogInformation("Solicitando producto con ID: {Id}", id);
    
    // Simular lógica...
    if (id < 0)
    {
        logger.LogWarning("Intento de acceso con ID negativo: {Id}", id);
        return Results.BadRequest();
    }

    return Results.Ok(new { Id = id });
});
Copied!
public class PaymentService
{
    private readonly ILogger<PaymentService> _logger;

    // Inyectamos el logger específico para esta clase
    public PaymentService(ILogger<PaymentService> logger)
    {
        _logger = logger;
    }

    public void ProcesarPago()
    {
        _logger.LogInformation("Iniciando proceso de pago...");
        
        try 
        {
            // Lógica compleja
        }
        catch(Exception ex)
        {
            // OJO: Pasamos la excepción como primer parámetro
            _logger.LogError(ex, "Error crítico procesando el pago");
        }
    }
}
Copied!

Logging estructurado

Fíjate en cómo he escrito el mensaje antes:

// ✅ BIEN: Structured Logging
logger.LogInformation("Solicitando producto con ID: {Id}", id);
Copied!

Y fijate como NO se haría,

// ❌ MAL: Concatenación de Strings
logger.LogInformation($"Solicitando producto con ID: {id}");
Copied!

¿Cuál es la diferencia?

  • En el MAL, se genera un string final: "Solicitando producto con ID: 5". Es solo texto plano.
  • En el BIEN, se guarda una plantilla y los datos por separado.

Esto permite que, si enviamos los logs a un sistema inteligente (como Application Insights, ElasticSearch o Seq), podamos hacer búsquedas como: SELECT * WHERE Id > 100

Configurando en appsettings.json

No queremos ver logs de Trace en producción, pero sí queremos verlos mientras desarrollamos. Esto se controla en el appsettings.json, en la sección Logging.

{
  "Logging": {
    "LogLevel": {
      "Default": "Information", // Por defecto, muéstrame Info para arriba
      "Microsoft.AspNetCore": "Warning" // ¡Silencia a Microsoft!
    }
  }
}
Copied!

Fíjate en la línea "Microsoft.AspNetCore": "Warning". El framework de ASP.NET es muy “charlatán”. Si lo pones en Information, te dirá cada vez que entra y sale de un middleware.

En producción, solemos subirlo a Warning para ver solo nuestros logs y los errores del framework.