Skip to content

Overview

La librería CodeDesignPlus.Net.Logger proporciona un marco robusto para la gestión centralizada de logs en aplicaciones .NET Core, utilizando Serilog como motor principal y ofreciendo la capacidad de exportar logs a OpenTelemetry (OTel) para un análisis más profundo. Esta librería facilita la configuración de logs enriquecidos con información contextual, mejorando la capacidad de depuración y monitoreo de aplicaciones.

Propósito y alcance


El objetivo principal de CodeDesignPlus.Net.Logger es simplificar la configuración y gestión de logs en aplicaciones .NET Core. Permite a los desarrolladores configurar fácilmente Serilog con enriquecimientos predefinidos, como el nombre de la aplicación, el entorno, el nombre del usuario, entre otros. Además, ofrece la flexibilidad de enviar estos logs a un sistema de telemetría como OTel, facilitando el análisis y la observación del comportamiento de la aplicación.

Principales características


  • Integración con Serilog: Utiliza Serilog como motor principal para logs, proporcionando todas sus capacidades y flexibilidad.
  • Enriquecimiento de logs: Agrega automáticamente información contextual a los logs, como el nombre de la aplicación, la máquina, el ID del proceso, etc.
  • Exportación a OpenTelemetry (OTel): Facilita la exportación de logs a un colector OTel, si está configurado, para análisis y monitoreo avanzados.
  • Configuración simplificada: Ofrece métodos de extensión para configurar los logs fácilmente en IServiceCollection e IHostBuilder.
  • Personalización: Permite la configuración personalizada de Serilog mediante acciones adicionales.
  • Detección de errores: Incluye destructores personalizados para excepciones de base de datos.

Casos de uso típicos


  • Centralización de logs en aplicaciones distribuidas.
  • Monitoreo y análisis de rendimiento de microservicios.
  • Depuración y diagnóstico de problemas en aplicaciones .NET Core.
  • Estandarización del formato de logs en múltiples proyectos.
  • Integración de logs con herramientas de observabilidad (e.g., Prometheus, Grafana).

Componentes Principales


  • ServiceCollectionExtension: Clase con métodos de extensión para configurar el logging en IServiceCollection.
  • AddLogger: Método de extensión que agrega los servicios de logging y las opciones de configuración a IServiceCollection.
  • UseSerilog: Método de extensión que configura Serilog para el IHostBuilder.
  • LoggerOptions: Clase que representa las opciones de configuración del logger, incluyendo la configuración de OTel.
  • Exceptions.LoggerException: Excepción que se lanza cuando la configuración del logger no es válida.
  • Directorysrc
    • DirectoryCodeDesignPlus.Net.Logger
      • DirectoryExceptions
        • LoggerException.cs
      • DirectoryExtensions
        • ServiceCollectionExtension.cs
      • DirectoryOptions
        • LoggerOptions.cs

Primeros Pasos


En esta sección, aprenderás a instalar y configurar la librería CodeDesignPlus.Net.Logger en tu proyecto de .NET.

Requisitos previos

  • .NET 8 o superior.
  • Un IDE compatible con .NET (Visual Studio, Visual Studio Code, etc.)
  • Conocimiento básico de desarrollo en .NET Core.
  • Una instancia de OTel si se desea exportar los logs.

Instalación

Para instalar la librería CodeDesignPlus.Net.Logger, puedes utilizar el administrador de paquetes NuGet o la CLI de .NET. A continuación, se muestra un ejemplo de cómo instalar la librería utilizando la CLI de .NET:

Terminal window
dotnet add package CodeDesignPlus.Net.Logger

Ejemplo rápido


El ejemplo CodeDesignPlus.Net.Logger.Sample muestra cómo configurar el logger en una aplicación .NET Core. A continuación, se muestra un ejemplo de cómo configurar el logger en tu proyecto:

// See https://aka.ms/new-console-template for more information
using CodeDesignPlus.Net.Logger.Extensions;
using CodeDesignPlus.Net.Logger.Sample;
var builder = Host.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((context, config) =>
{
config.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);
config.AddJsonFile($"appsettings.{context.HostingEnvironment.EnvironmentName}.json", optional: true, reloadOnChange: true);
})
.ConfigureServices((context, services) =>
{
services.AddLogging();
services.AddLogger(context.Configuration);
services.AddHostedService<FakeBackgroundService>();
})
.UseSerilog();
var host = builder.Build();
host.Run();
  1. Agregar configuración en appsettings.json:

    {
    "Core": {
    "Business": "CodeDesignPlus",
    "AppName": "sample-logger",
    "Version": "v1",
    "Description": "Sample of CodeDesignPlus.Net.Core",
    "Contact": {
    "Name": "CodeDesignPlus",
    "Email": "custom@outlook.com"
    }
    },
    "Logger": {
    "Enable": true,
    "OTelEndpoint": "http://localhost:4317"
    }
    }
  2. Ejecutar Docker Compose para levantar el contenedor de OTel:

    services:
    otel-collector:
    image: otel/opentelemetry-collector
    ports:
    - "4317:4317"
    - "4318:4318"
    volumes:
    - ./settings/collector-config.yaml:/etc/otelcol/config.yaml
    restart: always
  3. Creamos el servicio FakeBackgroundService que escribira logs cuando se inicie el programa.

    using System;
    namespace CodeDesignPlus.Net.Logger.Sample;
    public class FakeBackgroundService(ILogger<FakeBackgroundService> logger) : BackgroundService
    {
    protected override Task ExecuteAsync(CancellationToken stoppingToken)
    {
    logger.LogInformation("The FakeBackgroundService is running.");
    return Task.CompletedTask;
    }
    }
  4. Regisrramos los servicios del log en el host

    //...
    .ConfigureServices((context, services) =>
    {
    services.AddLogging();
    services.AddLogger(context.Configuration);
    })
    .UseSerilog();
  5. En la contenedor de OTel, podemos ver los logs generados por la aplicación.

    2024-12-09 17:47:40 2024-12-09T22:47:40.052Zinfoservice@v0.114.0/service.go:166Setting up own telemetry...
    2024-12-09 17:47:40 2024-12-09T22:47:40.056Zinfotelemetry/metrics.go:70Serving metrics{"address": "localhost:8888", "metrics level": "Normal"}
    2024-12-09 17:47:40 2024-12-09T22:47:40.056Zinfobuilders/builders.go:26Development component. May change in the future.{"kind": "exporter", "data_type": "logs", "name": "debug"}
    2024-12-09 17:47:40 2024-12-09T22:47:40.057Zinfobuilders/builders.go:26Development component. May change in the future.{"kind": "exporter", "data_type": "traces", "name": "debug"}
    2024-12-09 17:47:40 2024-12-09T22:47:40.058Zinfobuilders/builders.go:26Development component. May change in the future.{"kind": "exporter", "data_type": "metrics", "name": "debug"}
    2024-12-09 17:47:40 2024-12-09T22:47:40.059Zinfoservice@v0.114.0/service.go:238Starting otelcol...{"Version": "0.114.0", "NumCPU": 32}
    2024-12-09 17:47:40 2024-12-09T22:47:40.059Zinfoextensions/extensions.go:39Starting extensions...
    2024-12-09 17:47:40 2024-12-09T22:47:40.060Zwarninternal@v0.114.0/warning.go:40Using the 0.0.0.0 address exposes this server to every network interface, which may facilitate Denial of Service attacks.{"kind": "receiver", "name": "otlp", "data_type": "logs", "documentation": "https://github.com/open-telemetry/opentelemetry-collector/blob/main/docs/security-best-practices.md#safeguards-against-denial-of-service-attacks"}
    2024-12-09 17:47:40 2024-12-09T22:47:40.061Zinfootlpreceiver@v0.114.0/otlp.go:112Starting GRPC server{"kind": "receiver", "name": "otlp", "data_type": "logs", "endpoint": "0.0.0.0:4317"}
    2024-12-09 17:47:40 2024-12-09T22:47:40.062Zwarninternal@v0.114.0/warning.go:40Using the 0.0.0.0 address exposes this server to every network interface, which may facilitate Denial of Service attacks.{"kind": "receiver", "name": "otlp", "data_type": "logs", "documentation": "https://github.com/open-telemetry/opentelemetry-collector/blob/main/docs/security-best-practices.md#safeguards-against-denial-of-service-attacks"}
    2024-12-09 17:47:40 2024-12-09T22:47:40.063Zinfootlpreceiver@v0.114.0/otlp.go:169Starting HTTP server{"kind": "receiver", "name": "otlp", "data_type": "logs", "endpoint": "0.0.0.0:4318"}
    2024-12-09 17:47:40 2024-12-09T22:47:40.063Zinfoservice@v0.114.0/service.go:261Everything is ready. Begin running and processing data.
    2024-12-09 17:48:08 2024-12-09T22:48:08.698ZinfoLogs{"kind": "exporter", "data_type": "logs", "name": "debug", "resource logs": 1, "log records": 1}
    2024-12-09 17:48:08 2024-12-09T22:48:08.698ZinfoResourceLog #0
    2024-12-09 17:48:08 Resource SchemaURL: https://opentelemetry.io/schemas/v1.13.0
    2024-12-09 17:48:08 Resource attributes:
    2024-12-09 17:48:08 -> service.name: Str(MyMicroservice)
    2024-12-09 17:48:08 -> service.version: Str(v1)
    2024-12-09 17:48:08 -> service.description: Str(Sample of CodeDesignPlus.Net.Core)
    2024-12-09 17:48:08 -> service.business: Str(CodeDesignPlus)
    2024-12-09 17:48:08 -> service.contact.name: Str(CodeDesignPlus)
    2024-12-09 17:48:08 -> service.contact.email: Str(custom@outlook.com)
    2024-12-09 17:48:08 ScopeLogs #0
    2024-12-09 17:48:08 ScopeLogs SchemaURL:
    2024-12-09 17:48:08 InstrumentationScope CodeDesignPlus.Net.Logger.Sample.FakeBackgroundService
    2024-12-09 17:48:08 LogRecord #0
    2024-12-09 17:48:08 ObservedTimestamp: 2024-12-09 22:48:08.577921 +0000 UTC
    2024-12-09 17:48:08 Timestamp: 2024-12-09 22:48:08.577921 +0000 UTC
    2024-12-09 17:48:08 SeverityText: Information
    2024-12-09 17:48:08 SeverityNumber: Info(9)
    2024-12-09 17:48:08 Body: Str(The FakeBackgroundService is running.)
    2024-12-09 17:48:08 Attributes:
    2024-12-09 17:48:08 -> MachineName: Str(AORUSX570)
    2024-12-09 17:48:08 -> ThreadId: Int(1)
    2024-12-09 17:48:08 -> ProcessId: Int(131648)
    2024-12-09 17:48:08 -> ProcessName: Str(CodeDesignPlus.Net.Logger.Sample)
    2024-12-09 17:48:08 -> EnvironmentUserName: Str(AORUSX570\coded)
    2024-12-09 17:48:08 -> AppName: Str(MyMicroservice)
    2024-12-09 17:48:08 -> message_template.text: Str(The FakeBackgroundService is running.)
    2024-12-09 17:48:08 -> message_template.hash.md5: Str(592ad19be63a7296241d676c000a02bb)
    2024-12-09 17:48:08 Trace ID:
    2024-12-09 17:48:08 Span ID:
    2024-12-09 17:48:08 Flags: 0
    2024-12-09 17:48:08 {"kind": "exporter", "data_type": "logs", "name": "debug"}
    2024-12-09 17:48:10 2024-12-09T22:48:10.728ZinfoLogs{"kind": "exporter", "data_type": "logs", "name": "debug", "resource logs": 1, "log records": 3}
    2024-12-09 17:48:10 2024-12-09T22:48:10.728ZinfoResourceLog #0
    2024-12-09 17:48:10 Resource SchemaURL: https://opentelemetry.io/schemas/v1.13.0
    2024-12-09 17:48:10 Resource attributes:
    2024-12-09 17:48:10 -> service.name: Str(MyMicroservice)
    2024-12-09 17:48:10 -> service.version: Str(v1)
    2024-12-09 17:48:10 -> service.description: Str(Sample of CodeDesignPlus.Net.Core)
    2024-12-09 17:48:10 -> service.business: Str(CodeDesignPlus)
    2024-12-09 17:48:10 -> service.contact.name: Str(CodeDesignPlus)
    2024-12-09 17:48:10 -> service.contact.email: Str(custom@outlook.com)
    2024-12-09 17:48:10 ScopeLogs #0
    2024-12-09 17:48:10 ScopeLogs SchemaURL:
    2024-12-09 17:48:10 InstrumentationScope Microsoft.Hosting.Lifetime
    2024-12-09 17:48:10 LogRecord #0
    2024-12-09 17:48:10 ObservedTimestamp: 2024-12-09 22:48:08.5921085 +0000 UTC
    2024-12-09 17:48:10 Timestamp: 2024-12-09 22:48:08.5921085 +0000 UTC
    2024-12-09 17:48:10 SeverityText: Information
    2024-12-09 17:48:10 SeverityNumber: Info(9)
    2024-12-09 17:48:10 Body: Str(Application started. Press Ctrl+C to shut down.)
    2024-12-09 17:48:10 Attributes:
    2024-12-09 17:48:10 -> MachineName: Str(AORUSX570)
    2024-12-09 17:48:10 -> ThreadId: Int(1)
    2024-12-09 17:48:10 -> ProcessId: Int(131648)
    2024-12-09 17:48:10 -> ProcessName: Str(CodeDesignPlus.Net.Logger.Sample)
    2024-12-09 17:48:10 -> EnvironmentUserName: Str(AORUSX570\coded)
    2024-12-09 17:48:10 -> AppName: Str(MyMicroservice)
    2024-12-09 17:48:10 -> message_template.text: Str(Application started. Press Ctrl+C to shut down.)
    2024-12-09 17:48:10 -> message_template.hash.md5: Str(33343b9e9ae6b19943b4680fc45dba3e)
    2024-12-09 17:48:10 Trace ID:
    2024-12-09 17:48:10 Span ID:
    2024-12-09 17:48:10 Flags: 0
    2024-12-09 17:48:10 LogRecord #1
    2024-12-09 17:48:10 ObservedTimestamp: 2024-12-09 22:48:08.5955355 +0000 UTC
    2024-12-09 17:48:10 Timestamp: 2024-12-09 22:48:08.5955355 +0000 UTC
    2024-12-09 17:48:10 SeverityText: Information
    2024-12-09 17:48:10 SeverityNumber: Info(9)
    2024-12-09 17:48:10 Body: Str(Hosting environment: Production)
    2024-12-09 17:48:10 Attributes:
    2024-12-09 17:48:10 -> EnvName: Str(Production)
    2024-12-09 17:48:10 -> MachineName: Str(AORUSX570)
    2024-12-09 17:48:10 -> ThreadId: Int(1)
    2024-12-09 17:48:10 -> ProcessId: Int(131648)
    2024-12-09 17:48:10 -> ProcessName: Str(CodeDesignPlus.Net.Logger.Sample)
    2024-12-09 17:48:10 -> EnvironmentUserName: Str(AORUSX570\coded)
    2024-12-09 17:48:10 -> AppName: Str(MyMicroservice)
    2024-12-09 17:48:10 -> message_template.text: Str(Hosting environment: {EnvName})
    2024-12-09 17:48:10 -> message_template.hash.md5: Str(4d9ec9b8e5e077b29c981b666ca9117e)
    2024-12-09 17:48:10 Trace ID:
    2024-12-09 17:48:10 Span ID:
    2024-12-09 17:48:10 Flags: 0
    2024-12-09 17:48:10 LogRecord #2
    2024-12-09 17:48:10 ObservedTimestamp: 2024-12-09 22:48:08.5956514 +0000 UTC
    2024-12-09 17:48:10 Timestamp: 2024-12-09 22:48:08.5956514 +0000 UTC
    2024-12-09 17:48:10 SeverityText: Information
    2024-12-09 17:48:10 SeverityNumber: Info(9)
    2024-12-09 17:48:10 Body: Str(Content root path: G:\Repos\CodeDesignPlus.Net.Sdk\examples\CodeDesignPlus.Net.Logger.Sample\src\CodeDesignPlus.Net.Logger.Sample)
    2024-12-09 17:48:10 Attributes:
    2024-12-09 17:48:10 -> ContentRoot: Str(G:\Repos\CodeDesignPlus.Net.Sdk\examples\CodeDesignPlus.Net.Logger.Sample\src\CodeDesignPlus.Net.Logger.Sample)
    2024-12-09 17:48:10 -> MachineName: Str(AORUSX570)
    2024-12-09 17:48:10 -> ThreadId: Int(1)
    2024-12-09 17:48:10 -> ProcessId: Int(131648)
    2024-12-09 17:48:10 -> ProcessName: Str(CodeDesignPlus.Net.Logger.Sample)
    2024-12-09 17:48:10 -> EnvironmentUserName: Str(AORUSX570\coded)
    2024-12-09 17:48:10 -> AppName: Str(MyMicroservice)
    2024-12-09 17:48:10 -> message_template.text: Str(Content root path: {ContentRoot})
    2024-12-09 17:48:10 -> message_template.hash.md5: Str(8468f8e3d95716a49ff2b521b7133155)
    2024-12-09 17:48:10 Trace ID:
    2024-12-09 17:48:10 Span ID:
    2024-12-09 17:48:10 Flags: 0
    2024-12-09 17:48:10 {"kind": "exporter", "data_type": "logs", "name": "debug"}

Métodos de extensión


CodeDesignPlus.Net.Logger proporciona métodos de extensión para configurar los logs en IServiceCollection e IHostBuilder. A continuación, se muestran los métodos de extensión más importantes:

Service Collection


ServiceCollectionExtensions contiene los métodos de extensión para registrar los servicios necesarios en el contenedor de dependencias.

Opciones de configuración


CodeDesignPlus.Net.Logger utiliza la clase LoggerOptions para personalizar la configuración del logger y la exportación de logs a OTel.

Conclusiones


CodeDesignPlus.Net.Logger ofrece una solución eficiente y flexible para la gestión de logs en aplicaciones .NET Core. Facilita la configuración de Serilog con enriquecimientos automáticos y la posibilidad de exportar logs a OpenTelemetry, mejorando la observabilidad y la capacidad de diagnóstico de las aplicaciones.

Recursos externos