Dinaup.Logs (Logging)

¿Por qué Dinaup.Logs?

Dinaup.Logs nace de la necesidad de centralizar y estandarizar los registros de la plataforma Dinaup, aportando:

  • Trazabilidad completa de cada request y proceso.

  • Métricas automáticas para detectar cuellos de botella.

  • ElasticSearch como backend opcional para búsquedas y paneles en tiempo real.


Inicialización

Se recomienda inicializar Dinaup.Logs una vez al comienzo de la aplicación (por ejemplo, en Program.cs o en la rutina de arranque). Para ello, utiliza el método estático Logs.Initialize(...), proporcionando parámetros clave como el nombre y versión de la aplicación, la configuración de Elasticsearch (si se utiliza), la ruta del archivo de log, el entorno de ejecución y la opción autoExportContextMetric. Por ejemplo:

using Dinaup.Logs;

var elastic = new Logs.ElasticConfig("https://elastic.xxx.xxx", "xxxxx");
Logs.Initialize(
    applicationName: "XXXX",
    applicationVersion: "1.0.0",
    elasticConfig: elastic,
    logFilePath: "logs/log.txt",
    environment: Env.IsDevelopment() ? "Debug" : "Release",
    autoExportContextMetric: false
);

En este ejemplo se configura una conexión a Elasticsearch junto con un archivo local para los logs. La opción autoExportContextMetric está desactivada (false); puedes activarla (true) si deseas exportar automáticamente métricas de cada contexto de log al sistema de monitoreo.


Niveles y formato de logging

Dinaup.Logs envuelve Serilog, así que dispones de los niveles clásicos (Verbose, Debug, Information, Warning, Error, Fatal).

Logs.Information("Usuario {UserId} inició sesión", userId);
Logs.Warning("Balance negativo detectado: {Balance}", balance);

Cambia el nivel global en caliente si lo necesitas:

Logs.SetLoggingLevel(LogEventLevel.Debug);

Contextos enriquecidos

Los contextos añaden metadatos automáticos a cada mensaje sin esfuerzo:

5.1 BeginContext

Agrupa los logs de un proceso concreto y opcionalmente incrementa un contador.

public class PagosService
{
    public void GenerarFactura()
    {
        using (Logs.BeginContext(nameof(PagosService), nameof(GenerarFactura)))
        {
            Logs.Debug("Preparando borrador de factura");
            // ... tu lógica aquí
        }
    }
}

5.2 BeginCorrelationContext

Ideal para flujos distribuidos: incluye un CorrelationId que viaja por microservicios.

var correlationId = Guid.NewGuid().ToString();
using (Logs.BeginCorrelationContext(nameof(PagosService), nameof(GenerarFactura), correlationId))
{
    ...
}


Métricas integradas

Cuando activas autoExportContextMetric, cada llamada a BeginContext incrementa un CounterMetric etiquetado con component y action.

Crear contadores manuales:

static CounterMetric pagosOk = new CounterMetric("pagos_ok", "hit", 0, new() {{"status", "ok"}});
...
pagosOk.Increment();

Estas métricas se envían a Elastic Search.


Helpers HandleAction y HandleActionAsync

Envuelven código en un bloque try/catch con cronómetro incorporado y logean éxito o excepción.

var resultado = Logs.HandleAction(nameof(PagosService), nameof(Cobrar), () =>
{
   /// ...
}, new { pedido.Id, pedido.Total });

if (!resultado.IsOk) return Results.BadRequest(resultado.MessageException);

Versión asíncrona:

await Logs.HandleActionAsync(nameof(EmailService), nameof(EnviarFactura), async () =>
{
    await emailSender.SendAsync(...);
});

Buenas prácticas

  • No silencies excepciones: si atrapas una, logéala con Error y vuelve a lanzarla o maneja el resultado.

  • Evita logs sensibles (tokens, contraseñas). Usa propiedades parametrizadas.

  • Cierra al apagar la app: Logs.CloseAndFlush();

Última actualización