Saltar al contenido principal

Dinaup.Logs

Modulo de observabilidad de la libreria Dinaup que unifica logs estructurados, correlacion distribuida y metricas en aplicaciones .NET. Incluye envio opcional a OpenSearch.

Requisitos

Inicializacion

Con OpenSearch

var openSearchConfig = new Logs.OpenSearchConfig
{
Endpoint = "***",
Username = "***",
Password = "***"
};

Logs.Initialize(
applicationName: "MiApp",
applicationVersion: "1.0.0",
logFilePath: "logs/app.log",
openSearchConfig: openSearchConfig,
environment: "Production",
autoExportContextMetric: true
);

Logs.SetLoggingLevel(LogEventLevel.Debug);

Sin OpenSearch

Logs.Initialize(
applicationName: "MiApp",
applicationVersion: "1.0.0",
logFilePath: "logs/app.log",
openSearchConfig: null,
environment: "Dev",
autoExportContextMetric: true
);

Logs.SetLoggingLevel(LogEventLevel.Information);
aviso

Antes de detener la aplicacion, llama a Logs.CloseAndFlush() para enviar los datos pendientes.

Logs basicos y con contexto

// Basico
Logs.Information("Usuario {UserId} inicio sesion", userId);
Logs.Warning("Intentos fallidos {Count} para {User}", attempts, userEmail);
Logs.Error("Error al procesar pedido {OrderId}: {Message}", orderId, ex.Message);

// Con contexto (component + action)
using (Logs.BeginContext(nameof(StripeService), nameof(CreateInvoice)))
{
Logs.Debug("Generando factura para {OrderId}", orderId);
// ... logica ...
Logs.Information("Factura {InvoiceId} creada", invoiceId);
}

// Con correlacion distribuida
using (Logs.BeginCorrelationContext(nameof(JobWorker), nameof(RunAsync), correlationId))
{
Logs.Information("Procesando {Count} pedidos", orderIds.Count());
}

Metricas

CounterMetric

var counter = new Logs.CounterMetric(
metricName: "pagos_ok",
unit: "hit",
initial: 0.0m,
tags: new Dictionary<string, string> { { "status", "ok" }, { "component", "payments" } }
);

counter.Increment(); // +1
counter.Increment(5.0m); // +5
Logs.MetricExporter.Flush(); // exportar y resetear

HistogramMetric

var buckets = new List<Tuple<double, double>>
{
Tuple.Create(0.0, 100.0),
Tuple.Create(100.0, 200.0),
Tuple.Create(200.0, 500.0)
};

using (var hist = new Logs.HistogramMetric("response_time_ms", "ms", tags, buckets))
{
hist.Record(75); // bucket 0-100
hist.Record(150); // bucket 100-200
}

Helpers de ejecucion

HandleAction y HandleActionAsync envuelven codigo con try/catch, cronometro y logs coherentes:

var result = await Logs.HandleActionAsync(
component: nameof(PagosService),
action: nameof(PagosService.Cobrar),
actionToRunAsync: async () => { await ProcesarCobro(pedidoId); },
details: new { PedidoId = pedidoId }
);

if (result.IsOk == false)
{
Logs.Error("Fallo: {Error}", result.MessageException);
}

Middleware de correlacion

app.Use(async (context, next) =>
{
var correlationId = context.Request.Headers["X-Correlation-Id"].FirstOrDefault()
?? $"corr-{Guid.NewGuid():N}";

using (Logs.BeginCorrelationContext("HttpRequest", context.Request.Path.Value ?? "/", correlationId))
{
await next();
}
});