CodeGym /Cursos /C# SELF /Registro (logging): Micros...

Registro (logging): Microsoft.Extensions.Logging

C# SELF
Nivel 64 , Lección 0
Disponible

1. Introducción

En programación el logging no es simplemente "imprimir algo en la consola". El logging es tu caja negra, GPS-tracker e indicador en uno. Sin logs, una aplicación grande se convierte en una caja negra misteriosa: "¿por qué el servicio se colgó?", "¿por qué el usuario no recibió el correo?", "¿alguien había ejecutado este módulo en los últimos 3 meses?" — a todas esas preguntas muchas veces solo se puede responder si los logs se almacenan y están accesibles.

¿Para qué sirve el logging en la práctica?

Búsqueda y diagnóstico de errores
Si la aplicación se cayó — los logs dirán dónde y por qué. Si no se cayó pero funciona raro — los logs indicarán los pasos que llevaron a eso.

Monitorización del estado
Con los logs puedes saber si el sistema está funcionando ahora, cuántas peticiones recibe el servidor, si aparecen errores, quién y qué está haciendo.

Seguridad
Registrar intentos de acceso no autorizado, actividad sospechosa, errores de autenticación.

Auditoría
Quién, qué y cuándo hizo algo. Si un admin malintencionado se fue y borró datos, por los logs se puede reconstruir todo (o al menos entender qué hizo).

Soporte en desarrollo y operaciones
Los logs no son solo para el programador, también para QA, operadores y admins. Dentro de seis meses te vas a agradecer a ti mismo: '¡Gracias por añadir logs!'

De Console.WriteLine al logging industrial

La reacción inicial del novato: "¿No basta con hacer Console.WriteLine?". Para programas pequeños de aprendizaje eso puede ser suficiente. Pero cuando la app corre en servidor, es concurrente, o la usan decenas o cientos de usuarios, la consola ya no ayuda. Necesitas:

  • Separar información importante y debug.
  • Enviar logs no solo a la consola, sino a archivos, bases de datos, sistemas centralizados.
  • Cambiar el nivel de detalle de los logs (mínimo — solo errores, máximo — todo).
  • Añadir automáticamente fecha, hora y metadata a las entradas.
  • Configurar de forma flexible.
  • Y lo principal — no tener que cambiar el código para redirigir logs a otro lugar.

Aquí empieza la era de los "loggers" de verdad.

2. Fundamentos de un sistema moderno de logging en .NET

En el ecosistema .NET existe un framework estándar, potente y flexible para logging — Microsoft.Extensions.Logging. Es parte de la "nueva ola" de librerías .NET que aparecieron con ASP.NET Core, pero hoy se usa en todas partes: servidor, desktop e incluso móvil.

¿Qué hace bueno a este framework?

  • Abstracción — no te ata a una implementación concreta (el logger puede escribir en archivo, consola, cloud o en todo a la vez).
  • Soporte de niveles de logging (Trace, Debug, Information, Warning, Error, Critical).
  • Integración con el contenedor DI y en todas las apps .NET modernas.
  • Ecosistema rico: logging estructurado, formatters avanzados e integraciones.

Conceptos y clases principales

Conozcamos los objetos clave que necesitaremos para trabajar con Microsoft.Extensions.Logging:

Clase/Interfaz Propósito
ILogger<T>
Interfaz para logging, tipada por clase
ILogger
Interfaz genérica del logger
ILoggerFactory
Fábrica para crear instancias de loggers
ILoggingBuilder
Permite configurar el logging en la aplicación
LogLevel
Enumeración de niveles de logs (Trace, Debug, Information, ...)

Niveles de logging

Separar mensajes por nivel de importancia permite filtrar el "ruido" y encontrar lo necesario:

Nivel (LogLevel) ¿Para qué usar?
Trace
Trazas extremadamente detalladas, "ruido", datos temporales
Debug
Información principal de debugging
Information
Mensajes clave de eventos para funcionamiento normal
Warning
Advertencias sobre posibles problemas, pero el sistema sigue
Error
Errores que requieren atención, pero la app está viva
Critical
Fallos críticos que amenazan todo el sistema

3. Práctica: añadimos logging a nuestra aplicación

No vamos a escribir código abstracto; continuamos con nuestra app demo. Supongamos que ya tenemos una clase Calculator sencilla que vamos ampliando durante el curso.

Ejemplo: calculadora básica

public class Calculator
{
    public int Add(int a, int b)
    {
        return a + b;
    }
    // Resto de métodos...
}

Ahora integremos logging en ella. Para eso necesitamos la interfaz ILogger<Calculator>, que recibiremos desde afuera (por ejemplo, via Dependency Injection, DI).

using Microsoft.Extensions.Logging;

public class Calculator
{
    private readonly ILogger<Calculator> _logger;

    public Calculator(ILogger<Calculator> logger)
    {
        _logger = logger;
    }

    public int Add(int a, int b)
    {
        int result = a + b;
        _logger.LogInformation("Se realizó una suma: {A} + {B} = {Result}", a, b, result);
        return result;
    }
}

Dato interesante:
En lugar de concatenar strings, los loggers soportan plantillas y parámetros nombrados ({A}, {B}, {Result}), lo que permite logs estructurados y más fáciles de procesar y buscar automáticamente.

4. Cómo crear y configurar un logger en una app de consola

1. Añadir paquetes NuGet

En tu proyecto necesitarás:

  • Microsoft.Extensions.Logging
  • Microsoft.Extensions.Logging.Console (si quieres escribir en consola)
  • (opcional) otros providers según necesidad

2. Configurar el logger

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;

// Creamos el contenedor DI
var serviceProvider = new ServiceCollection()
    .AddLogging(builder => {
        builder.AddConsole(); // Salida a consola
        builder.SetMinimumLevel(LogLevel.Debug); // Nivel mínimo de logs
    })
    .BuildServiceProvider();

// Obtenemos el logger del tipo necesario
var logger = serviceProvider.GetRequiredService<ILogger<Calculator>>();

var calculator = new Calculator(logger);
calculator.Add(5, 3); // El mensaje irá a los logs

Error típico de novatos
"¿Por qué el log no aparece en la consola?" — revisa si añadiste el provider correcto (.AddConsole()) y si el nivel mínimo está bien configurado (SetMinimumLevel). Si el nivel es superior, ¡los mensajes pueden simplemente filtrarse!

5. Novedades útiles

Registrando errores y situaciones anómalas

Supongamos que queremos loggear una división por cero. Añadimos el método correspondiente:

public int Divide(int a, int b)
{
    if (b == 0)
    {
        _logger.LogError("Intento de división por cero! a={A}", a);
        throw new DivideByZeroException();
    }
    int result = a / b;
    _logger.LogInformation("Se realizó una división: {A} / {B} = {Result}", a, b, result);
    return result;
}

¿Por qué es útil?
En una app real, cuando algo sale mal, los logs con nivel Error suelen llamar atención: se envían a admins, se resaltan en monitorización y se usan para alertas/notificaciones.

Uso de categorías y etiquetas (scopes)

El logger en .NET soporta los llamados scopes — metadatos adicionales que se añaden automáticamente a todos los logs dentro de un bloque de código. Por ejemplo, al procesar una petición web o una sesión de usuario, puedes añadir su id al scope.

using (_logger.BeginScope("UserId: {UserId}", 42))
{
    _logger.LogInformation("Comenzó el procesamiento de los datos del usuario");
    // ...
}

Todos los mensajes dentro del bloque recibirán la etiqueta adicional UserId: 42, lo que ayuda a filtrar logs por usuario u operación.

Ejemplo: niveles de logging en acción

_logger.LogTrace("Esto es Trace — casi nadie lo verá");
_logger.LogDebug("Esto es Debug — para desarrolladores");
_logger.LogInformation("Esto es Information — para eventos de funcionamiento normal");
_logger.LogWarning("Esto es Warning — advertencia sobre posible problema");
_logger.LogError("Esto es Error — error que requiere atención");
_logger.LogCritical("Esto es Critical — ¡el sistema arde, llama a los bomberos!");

Si configuraste SetMinimumLevel(LogLevel.Information), verás solo mensajes de niveles Information, Warning, Error, Critical.

Consejo:
Deja Trace y Debug para diagnóstico detallado en desarrollo; en producción normalmente activan solo Information y superiores para no inflar los logs y no perder lo importante entre el "ruido".

Esquema visual: arquitectura del logging moderno

graph TD
A[Código de la aplicación] --ILogger<YourClass>--> B[Microsoft.Extensions.Logging]
B --> C1[Console Provider]
B --> C2[File Provider]
B --> C3[Cloud/Database Provider]
C1 -.-> D1[Logs en consola]
C2 -.-> D2[Logs en archivo]
C3 -.-> D3[Logs en sistema de monitorización]

subgraph Providers
    C1
    C2
    C3
end

6. Funcionalidades adicionales y extensiones

Logging estructurado:
Los valores de los parámetros se pueden almacenar no solo en la cadena, sino como pares clave-valor, lo que permite buscar y agregar por esos parámetros (por ejemplo con Seq, ELK/ElasticSearch o Application Insights).

Providers de logging:
Puedes añadir muchos providers: archivo, Windows EventLog, Azure, etc.

Configurar logging vía appsettings.json:
En ASP.NET Core el logging se configura fácilmente desde el archivo de configuración sin recompilar la app.

Ejemplo de configuración de niveles mínimos via config (appsettings.json):

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "MyApp.Calculator": "Debug",
      "Microsoft": "Warning"
    }
  }
}

7. Errores típicos al trabajar con Microsoft.Extensions.Logging

Error #1: Elección incorrecta del nivel de logging.
Usar LogInformation para errores en vez de LogError o LogCritical dificulta encontrar problemas en producción.

Error #2: Ignorar el logging estructurado.
Concatenar strings en vez de usar plantillas con placeholders ({Parameter}) te hace perder ventajas del logging estructurado, como buscar por parámetros.

Error #3: Configurar mal los niveles de logging.
Si el nivel mínimo está demasiado alto (por ejemplo Warning en vez de Debug), mensajes importantes pueden filtrarse.

Error #4: Logging excesivo o insuficiente.
Logs demasiado detallados (por ejemplo Trace en producción) crean "ruido", y la falta de logs dificulta el diagnóstico.

Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION