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
- Paquete NuGet: Dinaup
- OpenSearch gestionado (recomendado): OVHcloud OpenSearch
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();
}
});