Dinaup - Base de Conocimientos Help

Dinaup.Logs: Manual de Uso de la Biblioteca

Dinaup.Logs es una biblioteca de logging para aplicaciones .NET.

Requisitos Previos

Antes de comenzar, asegúrate de tener:

  • .NET 8

  • Acceso a un servidor de Elasticsearch si planeas utilizar este sink.

  • Webhooks configurados para Microsoft Teams y/o Mattermost si deseas enviar logs a estas plataformas.

Instalación

  1. Agregar la Biblioteca Dinaup.Logs:

Install-Package Dinaup.Logs

Configuración

Configuración de Elasticsearch

Para enviar logs a Elasticsearch, necesitas proporcionar detalles de conexión mediante la clase ElasticConfig.

public class ElasticConfig { public string Endpoint { get; set; } public string Username { get; set; } public string Password { get; set; } public string IndexPrefix { get; set; } }

Ejemplo de Configuración:

var elasticConfig = new ElasticConfig { Endpoint = "http://localhost:9200", Username = "usuario", Password = "contraseña", IndexPrefix = "miapp" };

Configuración de Integraciones (Teams y Mattermost)

Para enviar logs a plataformas como Microsoft Teams o Mattermost, utiliza la clase IntegrationsConfig.

public class IntegrationsConfig { public string MattermostWebhook { get; set; } public string TeamsWebhook { get; set; } }

Ejemplo de Configuración:

var integrationsConfig = new IntegrationsConfig { TeamsWebhook = "https://outlook.office.com/webhook/...", MattermostWebhook = "https://mattermost.example.com/hooks/..." };

Inicialización de la Biblioteca

Antes de utilizar Dinaup.Logs, debes inicializarla con la configuración adecuada.

Dinaup.Logs.Initialize( applicationName: "MiAplicación", applicationVersion: "1.0.0", elasticConfig: elasticConfig, // Puede ser null si no usas Elasticsearch integrationsConfig: integrationsConfig, // Puede ser null si no usas integraciones logFilePath: "logs/app.log", environment: "Producción", autoExportContextMetric: true );

Parámetros de Inicialización:

  • applicationName: Nombre de la aplicación.

  • applicationVersion: Versión de la aplicación.

  • elasticConfig: Configuración de Elasticsearch (opcional).

  • integrationsConfig: Configuración de integraciones como Teams o Mattermost (opcional).

  • logFilePath: Ruta del archivo de logs.

  • environment: Entorno de ejecución (e.g., Desarrollo, Producción).

  • autoExportContextMetric: Habilita la exportación automática de métricas de contexto.

Métodos de Logging

Dinaup.Logs ofrece métodos para registrar logs en diferentes niveles de severidad.

Logging Básico

Los métodos disponibles son:

  • Verbose: Información detallada, útil para diagnóstico.

  • Debug: Información útil para depuración.

  • Information: Información general sobre el flujo de la aplicación.

  • Warning: Indicaciones de posibles problemas.

  • Error: Errores que no detienen la aplicación.

  • Fatal: Errores críticos que probablemente detendrán la aplicación.

Ejemplo de Uso:

Dinaup.Logs.Verbose("Este es un mensaje verbose."); Dinaup.Logs.Debug("Este es un mensaje debug."); Dinaup.Logs.Information("Este es un mensaje de información."); Dinaup.Logs.Warning("Este es un mensaje de advertencia."); Dinaup.Logs.Error("Este es un mensaje de error."); Dinaup.Logs.Fatal("Este es un mensaje fatal.");

Logging con Excepciones

Además de los mensajes básicos, puedes registrar excepciones para obtener detalles completos del error.

Ejemplo de Uso:

try { // Código que puede lanzar una excepción throw new Exception("Error de ejemplo."); } catch (Exception ex) { Dinaup.Logs.Error(ex, "Ocurrió una excepción inesperada."); }

Gestión de Contexto

La gestión de contexto permite agregar información adicional a los logs, facilitando el seguimiento de eventos relacionados.

Contexto Simple

Puedes iniciar un contexto usando BeginContext, que agrega propiedades al contexto de logging utilizando nameof() para los componentes y acciones.

Ejemplo de Uso dentro de una Clase y Método:

public class Procesamiento { public void IniciarProceso() { using (Dinaup.Logs.BeginContext(nameof(Procesamiento), nameof(IniciarProceso))) { Dinaup.Logs.Information("Proceso iniciado."); // Lógica del proceso... } } }

Al finalizar el bloque using, el contexto se descarta automáticamente.

Contexto con Correlación

Para rastrear eventos relacionados a través de diferentes partes de la aplicación, utiliza BeginCorrelationContext con un CorrelationId.

Ejemplo de Uso dentro de una Clase y Método:

public class ServicioPedido { public void ProcesarPedido(Guid pedidoId) { Dinaup.Logs.ValidateParameter(pedidoId, nameof(pedidoId)); var correlationId = Guid.NewGuid().ToString(); using (Dinaup.Logs.BeginCorrelationContext(nameof(ServicioPedido), nameof(ProcesarPedido), correlationId)) { Dinaup.Logs.Information("Iniciando el procesamiento del pedido."); // Lógica de procesamiento... ConfirmarPedido(); } } private void ConfirmarPedido() { using (Dinaup.Logs.BeginContext(nameof(ServicioPedido), nameof(ConfirmarPedido))) { Dinaup.Logs.Debug("Confirmando el pedido."); // Más lógica... } } }

En este ejemplo, tanto ProcesarPedido como ConfirmarPedido comparten el mismo CorrelationId, permitiendo rastrear todos los logs relacionados con esta operación.

Validación de Parámetros

Dinaup.Logs ofrece métodos para validar parámetros y registrar errores automáticamente si las validaciones fallan.

Métodos Disponibles:

  • ValidateParameter(Guid param, string paramName)

  • ValidateParameter<T>(T param, string paramName)

  • ValidateParameter(string param, string paramName)

  • ValidateParameter(IEnumerable param, string paramName, int maxItems)

  • ValidateParameter(IEnumerable param, string paramName)

Ejemplo de Uso:

public void ProcesarDatos(Guid id, string nombre, IEnumerable<string> items) { Dinaup.Logs.ValidateParameter(id, nameof(id)); Dinaup.Logs.ValidateParameter(nombre, nameof(nombre)); Dinaup.Logs.ValidateParameter(items, nameof(items), 100); // Continuar con el procesamiento... }

Si alguno de los parámetros no cumple con las condiciones, se registrará un error y se lanzará una excepción correspondiente.

Cómo Cambiar el Nivel de Logging

La biblioteca utiliza un LoggingLevelSwitch de Serilog que puede ser ajustado en tiempo de ejecución. Para cambiar el nivel de logging, utiliza el método SetLoggingLevel.

Ejemplo de Cambio de Nivel de Logging:

// Cambiar el nivel de logging a Debug Dinaup.Logs.SetLoggingLevel(Serilog.Events.LogEventLevel.Debug); // Más tarde, cambiar el nivel de logging a Warning Dinaup.Logs.SetLoggingLevel(Serilog.Events.LogEventLevel.Warning);

Cerrar y Volcar Logs

Es importante cerrar y volcar los logs al finalizar la aplicación para asegurarse de que todos los eventos sean persistidos correctamente.

Dinaup.Logs.CloseAndFlush();

Se recomienda llamar a este método en eventos de cierre de la aplicación, como en el método Main o en manejadores de eventos de cierre.

Consideraciones Finales

  • Manejo de Excepciones Globales: La biblioteca está configurada para capturar excepciones no manejadas y excepciones de tareas no observadas, registrándolas automáticamente como Fatal.

  • Rendimiento: Al configurar los sinks y el nivel de logging apropiadamente, puedes optimizar el rendimiento de tu aplicación evitando la sobrecarga de logs innecesarios.

  • Extensibilidad: Dinaup.Logs puede ser extendida para soportar nuevos sinks o funcionalidades adicionales, aprovechando la flexibilidad de Serilog.

  • Seguridad: Asegúrate de proteger las credenciales y endpoints sensibles utilizados en las configuraciones, especialmente al manejar autenticaciones básicas para Elasticsearch.

Uso de Métricas

Dinaup.Logs soporta principalmente dos tipos de métricas:

  • CounterMetric se utiliza para contar eventos específicos, como el número de solicitudes recibidas, archivos subidos, o errores ocurridos. Es una métrica incrementable que refleja la cantidad total de veces que un evento ha ocurrido.

  • HistogramMetric permite distribuir eventos en diferentes rangos o "buckets". Es útil para medir la distribución de valores, como los tiempos de respuesta de una API, tamaños de archivos, etc.

Inicialización de Métricas

Antes de utilizar las métricas, asegúrate de haber inicializado Dinaup.Logs correctamente. La recolección automática de métricas puede ser habilitada durante la inicialización.

var elasticConfig = new ElasticConfig { Endpoint = "http://localhost:9200", Username = "usuario", Password = "contraseña", IndexPrefix = "miapp" }; var integrationsConfig = new IntegrationsConfig { TeamsWebhook = "https://outlook.office.com/webhook/..." }; Dinaup.Logs.Initialize( applicationName: "MiAplicación", applicationVersion: "1.0.0", elasticConfig: elasticConfig, integrationsConfig: integrationsConfig, logFilePath: "logs/app.log", environment: "Producción", autoExportContextMetric: true );
  • autoExportContextMetric: Al establecerse en true, las métricas relacionadas con el contexto se exportarán automáticamente.

Uso de CounterMetric

Descripción

CounterMetric es ideal para contar eventos discretos. Cada vez que ocurre un evento, se incrementa el contador correspondiente.

Ejemplo de Uso

public class ServicioArchivo { public void SubirArchivo(string usuario) { // Contador de Archivos Subidos using (var contadorArchivosSubidos = new CounterMetric("ArchivosSubidos")) { contadorArchivosSubidos.Increment(); contadorArchivosSubidos.Increment(); Dinaup.Logs.Information("Archivo subido por el usuario {Usuario}.", usuario); // Lógica para subir el archivo... } // Contador de Llamadas API por Usuario foreach (var usuarioActual in new[] { "Salva", "Angel", "Paco de Lucia" }) { using (var contadorLlamadasAPI = new CounterMetric("LlamadasAPI", "request", 0, new Dictionary<string, string> { { "usuario", usuarioActual } })) { contadorLlamadasAPI.Increment(); Dinaup.Logs.Information("Llamada a API por el usuario {Usuario}.", usuarioActual); // Lógica de la llamada a la API... } } // Exportar las métricas actuales al sistema de métricas (por ejemplo, Elasticsearch) MetricExporter.Flush(); } }

Explicación:

  1. Creación del CounterMetric:

    • new CounterMetric("ArchivosSubidos"): Crea un contador llamado "ArchivosSubidos".

    • new CounterMetric("LlamadasAPI", "request", 0, tags): Crea un contador "LlamadasAPI" de tipo "request" con un conteo inicial de 0 y etiquetas adicionales.

  2. Incremento del Contador:

    • contadorArchivosSubidos.Increment();: Incrementa el contador en 1.

    • Puedes llamar a Increment() múltiples veces según sea necesario.

  3. Exportación de Métricas:

    • MetricExporter.Flush();: Envía las métricas recolectadas al backend configurado (por ejemplo, Elasticsearch).

Uso de HistogramMetric

Descripción

HistogramMetric se utiliza para distribuir valores en rangos específicos (buckets). Es útil para analizar la distribución de métricas como tiempos de respuesta, tamaños de archivos, etc.

Ejemplo de Uso

public class ServicioAPI { public void ProcesarSolicitud() { // Definir los rangos de los buckets para el histograma de tiempos de respuesta (en ms) var responseTimeBuckets = new List<Tuple<double, double>> { Tuple.Create(0.0, 100.0), Tuple.Create(100.0, 200.0), Tuple.Create(200.0, 300.0), Tuple.Create(300.0, 400.0), Tuple.Create(400.0, 500.0) }; // Definir etiquetas adicionales para categorizar el histograma var tags = new Dictionary<string, string> { { "endpoint", "api/v1/resource" }, { "usuario", "paco" } }; // Crear una instancia de HistogramMetric para medir los tiempos de respuesta de la API using (var responseTimeHistogram = new HistogramMetric("TiemposRespuestaAPI", "duration_request", tags, responseTimeBuckets)) { // Simular el registro de diferentes tiempos de respuesta de la API responseTimeHistogram.Record(50); // Incrementa el bucket 0-100 ms responseTimeHistogram.Record(150); // Incrementa el bucket 100-200 ms responseTimeHistogram.Record(250); // Incrementa el bucket 200-300 ms responseTimeHistogram.Record(350); // Incrementa el bucket 300-400 ms responseTimeHistogram.Record(450); // Incrementa el bucket 400-500 ms responseTimeHistogram.Record(-10); // Incrementa el bucket underflow responseTimeHistogram.Record(600); // Incrementa el bucket overflow // Exportar las métricas actuales al sistema de métricas (por ejemplo, Elasticsearch) MetricExporter.Flush(); // Simular el registro de más tiempos de respuesta de la API responseTimeHistogram.Record(120); // Incrementa el bucket 100-200 ms responseTimeHistogram.Record(220); // Incrementa el bucket 200-300 ms responseTimeHistogram.Record(320); // Incrementa el bucket 300-400 ms // Exportar las métricas actualizadas al sistema de métricas MetricExporter.Flush(); } // Confirmación de que las métricas han sido exportadas correctamente Dinaup.Logs.Information("Histogram metrics exported successfully."); } }

Explicación:

  1. Definición de Buckets:

    • Se crean rangos específicos para categorizar los tiempos de respuesta de la API.

  2. Etiquetas Adicionales:

    • Las etiquetas (tags) permiten categorizar aún más las métricas, facilitando su filtrado y análisis posterior.

  3. Creación del HistogramMetric:

    • new HistogramMetric("TiemposRespuestaAPI", "duration_request", tags, responseTimeBuckets): Crea un histograma llamado "TiemposRespuestaAPI" de tipo "duration_request" con las etiquetas y buckets definidos.

  4. Registro de Valores:

    • responseTimeHistogram.Record(50);: Registra un tiempo de respuesta de 50 ms, incrementando el bucket correspondiente.

    • Valores fuera de los rangos definidos incrementan los buckets de underflow o overflow.

  5. Exportación de Métricas:

    • MetricExporter.Flush();: Envía las métricas recolectadas al backend configurado.

Exportación de Métricas

Para que las métricas recolectadas sean útiles, deben ser enviadas a un backend donde puedan ser almacenadas y analizadas. Dinaup.Logs utiliza un componente llamado MetricExporter para manejar esta exportación.

Ejemplo de Exportación

// Después de recolectar métricas MetricExporter.Flush();

Consideraciones:

  • Asegúrate de que MetricExporter.Flush() esté correctamente implementado para enviar las métricas al backend deseado, como Elasticsearch, Prometheus, etc.

  • Puedes configurar MetricExporter para que realice la exportación en intervalos regulares o manualmente después de recolectar un conjunto de métricas.

Acceso y Visualización de Métricas

Para acceder a las métricas recolectadas, es necesario implementar métodos que expongan estas métricas desde la clase Dinaup.Logs. A continuación, se muestra cómo podrías implementar y utilizar dichos métodos.

Implementación de Métodos para Exponer Métricas

public static class Logs { // ... Otros métodos y propiedades ... private static ConcurrentDictionary<string, CounterMetric> metricCounter_Context = new ConcurrentDictionary<string, CounterMetric>(); private static ConcurrentDictionary<string, HistogramMetric> metricHistogram_Context = new ConcurrentDictionary<string, HistogramMetric>(); public static IEnumerable<CounterMetric> GetAllCounterMetrics() { return metricCounter_Context.Values; } public static IEnumerable<HistogramMetric> GetAllHistogramMetrics() { return metricHistogram_Context.Values; } // ... Implementación de métodos para agregar y gestionar métricas ... }

Ejemplo de Acceso a Métricas

public class MonitorMetrica { public void MostrarMetricas() { var counterMetrics = Dinaup.Logs.GetAllCounterMetrics(); var histogramMetrics = Dinaup.Logs.GetAllHistogramMetrics(); Console.WriteLine("=== Counter Metrics ==="); foreach (var metrica in counterMetrics) { Console.WriteLine($"Nombre: {metrica.Name}, Tipo: {metrica.Type}, Conteo: {metrica.Count}"); foreach (var tag in metrica.Tags) { Console.WriteLine($"\t{tag.Key}: {tag.Value}"); } } Console.WriteLine("\n=== Histogram Metrics ==="); foreach (var metrica in histogramMetrics) { Console.WriteLine($"Nombre: {metrica.Name}, Tipo: {metrica.Type}"); foreach (var tag in metrica.Tags) { Console.WriteLine($"\t{tag.Key}: {tag.Value}"); } foreach (var bucket in metrica.Buckets) { var count = metrica.BucketCounts[bucket]; Console.WriteLine($"\tBucket [{bucket.Item1} - {bucket.Item2}]: {count}"); } // Mostrar underflow y overflow var underflow = Tuple.Create(double.MinValue, metrica.Buckets.First().Item1); var overflow = Tuple.Create(metrica.Buckets.Last().Item2, double.MaxValue); Console.WriteLine($"\tBucket Underflow [{underflow.Item1} - {underflow.Item2}]: {metrica.BucketCounts[underflow]}"); Console.WriteLine($"\tBucket Overflow [{overflow.Item1} - {overflow.Item2}]: {metrica.BucketCounts[overflow]}"); } } }

Explicación:

  1. Recuperación de Métricas:

    • GetAllCounterMetrics(): Obtiene todas las métricas de tipo contador.

    • GetAllHistogramMetrics(): Obtiene todas las métricas de tipo histograma.

  2. Visualización de Métricas:

    • Se iteran las métricas recuperadas y se muestran sus detalles, incluyendo nombres, tipos, conteos y etiquetas.

    • Para las métricas de histograma, también se muestran los conteos por cada bucket, incluyendo underflow y overflow.

Consideraciones Adicionales

  • Implementación de MetricExporter: Asegúrate de que MetricExporter esté correctamente implementado para enviar las métricas al backend deseado. Esto puede incluir la configuración de endpoints, autenticación y formatos de datos.

  • Rendimiento: La recolección y exportación de métricas debe ser eficiente para no afectar el rendimiento de la aplicación. Considera implementar mecanismos de buffering o exportación asíncrona.

  • Seguridad: Protege las credenciales y endpoints utilizados para la exportación de métricas, especialmente si se envían a servicios externos como Elasticsearch.

  • Escalabilidad: Diseña la recolección y exportación de métricas de manera que escale con el crecimiento de la aplicación, manejando un gran volumen de eventos y datos sin degradar el rendimiento.

  • Personalización de Métricas: Puedes extender las funcionalidades de métricas según las necesidades específicas de tu aplicación, agregando nuevas métricas o tipos según sea necesario.

Este documento proporciona una guía detallada para utilizar las funcionalidades de métricas en Dinaup.Logs. Al implementar y gestionar métricas de manera efectiva, podrás obtener insights valiosos sobre el rendimiento y comportamiento de tus aplicaciones, facilitando la toma de decisiones informadas y la optimización continua.

Last modified: 04 February 2025