Utilice OpenTelemetry con OTLP y el Aspire Dashboard

En este artículo se muestra cómo instrumentar una API web de .NET con OpenTelemetry y enviar sus registros, métricas y seguimientos al Aspire panel mediante OTLP. Agregue los paquetes OpenTelemetry, configure métricas y seguimientos personalizados y vea los resultados en el panel.

El Aspire panel es una parte estándar de Aspire, pero también está disponible como un contenedor de Docker independiente que proporciona un punto de conexión de OTLP para enviar telemetría. El panel visualiza los registros, las métricas y los seguimientos. El uso del panel de esta manera no depende de Aspirey visualiza la telemetría desde cualquier aplicación que envíe telemetría mediante OTLP. Funciona igualmente bien para las aplicaciones escritas en Java, Go o Python, siempre que puedan enviar su telemetría a un punto de conexión de OTLP.

El Aspire panel requiere menos configuración y menos pasos de configuración que soluciones de código abierto como Prometheus, Grafana y Jaeger. Pero a diferencia de esas herramientas, el Aspire panel es una herramienta de visualización para desarrolladores, no una herramienta de supervisión de producción.

1. Creación del proyecto

Cree un proyecto de API web sencillo utilizando la plantilla ASP.NET Core Vacía en Visual Studio o el siguiente comando de la CLI de .NET:

dotnet new web

2. Hacer referencia a los paquetes de OpenTelemetry

Para agregar los paquetes OpenTelemetry, use el Administrador de paquetes NuGet o ejecute los siguientes dotnet add package comandos:

dotnet add package OpenTelemetry.Exporter.OpenTelemetryProtocol
dotnet add package OpenTelemetry.Extensions.Hosting
dotnet add package OpenTelemetry.Instrumentation.AspNetCore
dotnet add package OpenTelemetry.Instrumentation.Http

Como alternativa, agregue los siguientes PackageReference elementos directamente al archivo del proyecto:

<ItemGroup>
  <PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.19.1" />
  <PackageReference Include="OpenTelemetry.Extensions.Hosting" Version="1.19.1" />
  <PackageReference Include="OpenTelemetry.Instrumentation.AspNetCore" Version="1.19.0" />
  <PackageReference Include="OpenTelemetry.Instrumentation.Http" Version="1.19.0" />
</ItemGroup>

Nota:

Dado que las API de OTel evolucionan constantemente, use las versiones más recientes.

3. Añadir directivas de uso

Agregue las siguientes using directivas a la parte superior del archivo:

using System.Diagnostics;
using System.Diagnostics.Metrics;
using OpenTelemetry.Exporter;
using OpenTelemetry.Logs;
using OpenTelemetry.Metrics;
using OpenTelemetry.Resources;
using OpenTelemetry.Trace;

4. Agregar métricas y definiciones de actividad

El código siguiente define una nueva métrica (greetings.count) que cuenta cuántas veces un cliente llama a la API y un nuevo origen de actividad (Otel.Example). Inserte este código antes de builder.Build:

// Custom metrics for the application
var greeterMeter = new Meter("OTel.Example", "1.0.0");
var countGreetings = greeterMeter.CreateCounter<int>("greetings.count", description: "Counts the number of greetings");

// Custom ActivitySource for the application
var greeterActivitySource = new ActivitySource("OTel.Example");

5. Configuración de OpenTelemetry con los proveedores correctos

Inserte el siguiente código antes de builder.Build:

// Configure the shared OTLP connection used by logs, metrics, and traces.
var otlpEndpoint = new Uri(builder.Configuration["OTEL_EXPORTER_OTLP_ENDPOINT"]!);
Action<OtlpExporterOptions> configureOtlp = options =>
{
    options.Endpoint = otlpEndpoint;
    options.Protocol = OtlpExportProtocol.Grpc;
    options.Headers = builder.Configuration["OTEL_EXPORTER_OTLP_HEADERS"]; // To secure endpoint (not in this example)
};

// Setup logging to be exported via OpenTelemetry
builder.Logging.AddOpenTelemetry(logging =>
{
    logging.IncludeFormattedMessage = true;
    logging.IncludeScopes = true;
    logging.AddOtlpExporter(configureOtlp);
});

var otel = builder.Services.AddOpenTelemetry();

// Identify this application as a single service in the Aspire dashboard.
otel.ConfigureResource(resource => resource.AddService(builder.Configuration["OTEL_SERVICE_NAME"]!));

// Add Metrics for ASP.NET Core and our custom metrics and export via OTLP
otel.WithMetrics(metrics =>
{
    // Metrics provider from OpenTelemetry
    metrics.AddAspNetCoreInstrumentation();

    // Our custom metrics
    metrics.AddMeter(greeterMeter.Name);

    // Metrics provided by ASP.NET Core in .NET
    metrics.AddMeter("Microsoft.AspNetCore.Hosting");
    metrics.AddMeter("Microsoft.AspNetCore.Server.Kestrel");

    // Export the metrics via OTLP
    metrics.AddOtlpExporter(configureOtlp);
});

// Add Tracing for ASP.NET Core and our custom ActivitySource and export via OTLP
otel.WithTracing(tracing =>
{
    tracing.AddAspNetCoreInstrumentation();
    tracing.AddHttpClientInstrumentation();
    tracing.AddSource(greeterActivitySource.Name);
    tracing.AddOtlpExporter(configureOtlp);
});

Este código configura OpenTelemetry con los distintos orígenes de telemetría:

  • Añade un proveedor de OTel a ILogger para recopilar registros.
  • Configura métricas, registrando proveedores de instrumentación y medidores para ASP.NET y el medidor personalizado.
  • Configura el rastreo, registra los proveedores de instrumentación y el ActivitySource personalizado.

A continuación, registra el exportador de OTLP mediante variables de entorno para su configuración.

6. Configuración de las opciones de OTLP

Puede configurar el exportador de OTLP a través de API en código, variables de entorno o configuración de la aplicación. En este ejemplo, añada la configuración de OTLP en la raíz de appsettings.Development.json, después de la sección Logging:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "OTEL_EXPORTER_OTLP_ENDPOINT": "http://localhost:4317",
  "OTEL_SERVICE_NAME": "OTLP-Example"
}

Agregue otras opciones de configuración para el exportador de OTLP de .NET o la configuración común de OTel, como OTEL_RESOURCE_ATTRIBUTES para definir atributos de recursos.

Nota:

ASP.NET Core carga tanto appsettings.json como appsettings.Development.json. La configuración de appsettings.Development.json invalida la configuración duplicada en appsettings.json al ejecutar la aplicación en el entorno de desarrollo.

7. Creación de un punto de conexión de API

Inserte el código siguiente entre builder.Build y app.Run():

app.MapGet("/", SendGreeting);

Inserte la siguiente función al final del archivo:

async Task<string> SendGreeting(ILogger<Program> logger)
{
    // Create a new Activity scoped to the method
    using var activity = greeterActivitySource.StartActivity("GreeterActivity");

    // Log a message
    logger.LogInformation("Sending greeting");

    // Increment the custom counter
    countGreetings.Add(1);

    // Add a tag to the Activity
    activity?.SetTag("greeting", "Hello World!");

    return "Hello World!";
}

Nota:

La definición del punto de conexión no usa nada específico para OpenTelemetry. Usa las API de .NET para la observabilidad.

8. Inicia el contenedor del panel de control Aspire

Use docker para descargar y ejecutar el contenedor del panel.

docker run --rm -it `
-p 18888:18888 `
-p 4317:18889 `
--name aspire-dashboard `
mcr.microsoft.com/dotnet/aspire-dashboard:latest

Los datos que aparecen en el panel pueden ser confidenciales. De forma predeterminada, el panel requiere un token de autenticación para iniciar sesión. El contenedor muestra este token en su salida.

AspirePanel

Copie la dirección URL, sustituya 0.0.0.0 por localhost, por ejemplo, http://localhost:18888/login?t=123456780abcdef123456780, y ábrala en su navegador. O bien, pegue la clave después /login?t= en el cuadro de diálogo de inicio de sesión. El token cambia cada vez que se inicia el contenedor.

9. Ejecutar el proyecto

Ejecute el proyecto con dotnet run. La salida de la consola muestra las direcciones URL en las que escucha la aplicación, por ejemplo:

info: Microsoft.Hosting.Lifetime[14]
      Now listening on: http://localhost:5086

Use el puerto que se muestra en su propia salida de consola, ya que puede diferir de los ejemplos de este artículo. Use un explorador o curl para acceder a la API en ese puerto:

curl -k http://localhost:5086

Cada vez que solicite la página, aumenta el recuento de saludos.

9.1 Salida de registro

El código registra instrucciones mediante ILogger. De forma predeterminada, .NET habilita el proveedor de consola, que dirige la salida a la consola.

Puede exportar registros desde .NET de varias maneras:

  • Los sistemas de contenedores como Kubernetes redirigen la salida de stdout y stderr a archivos de registro.
  • Use bibliotecas de registro que se integren con ILogger, como Serilog y NLog.
  • Use proveedores de registro para OTel, como OTLP. La sección de registro del código del paso 5 agrega el proveedor OTel.

El panel muestra los registros como registros estructurados. Las propiedades establecidas en el mensaje de registro se convierten en campos en el registro de registro.

Registros en el panel independiente

9.2 Vista de métricas

El Aspire panel muestra las métricas por recurso. Un recurso es el término OTel para una fuente de telemetría, como un proceso. Al seleccionar un recurso, el panel muestra cada métrica que el recurso envió a su punto de conexión de OTLP. La lista de métricas es dinámica y se actualiza a medida que el panel recibe nuevas métricas.

Métricas en el panel independiente

La vista de métricas depende del tipo de métrica que use:

  • El panel muestra los contadores directamente.
  • Para los histogramas que registran un valor por solicitud, como un intervalo temporal o los bytes enviados por solicitud, el panel recopila los valores en una serie de intervalos y representa gráficamente los percentiles P50, P90 y P99. Los resultados del histograma pueden incluir ejemplos, que son puntos de datos individuales junto con el ID de rastreo/span de esa solicitud. El panel muestra estos puntos en el gráfico. Seleccione uno de ellos para ir a la traza correspondiente, para que pueda ver qué causó ese valor. Esta característica le ayuda a diagnosticar valores atípicos.
  • Las métricas pueden incluir dimensiones, que son pares clave-valor asociados a valores concretos. El panel agrega valores por dimensión. Usa las listas desplegables de la vista para filtrar los resultados por dimensiones específicas, como solo las solicitudes GET o una ruta URL específica en ASP.NET.

9.3 Vista de rastreo

La vista de rastreo muestra las trazas. Cada seguimiento es un conjunto de actividades que comparten el mismo identificador de seguimiento. Los spans realizan un seguimiento del trabajo, y cada span representa una unidad de trabajo. El procesamiento de una solicitud de ASP.NET crea un intervalo. La realización de una solicitud HttpClient es un intervalo. Al realizar un seguimiento del elemento primario de cada intervalo, se crea una jerarquía de intervalos que se pueden visualizar. Al recopilar intervalos de cada recurso (proceso), puede realizar un seguimiento del trabajo en una serie de servicios. Las solicitudes HTTP incluyen un encabezado que pasa el identificador de seguimiento y el identificador de intervalo primario al siguiente servicio. Cada recurso debe recopilar telemetría y enviarlo al mismo recopilador, que luego agrega y presenta una jerarquía de los intervalos.

Seguimientos en el panel independiente

El panel de control muestra una lista de rastros con información resumida. Cada vez que el panel detecta intervalos con un nuevo identificador de seguimiento, agrega una fila a la tabla. Seleccione Ver para mostrar todos los intervalos del seguimiento.

Intervalos en el panel independiente

Seleccione un intervalo para mostrar sus detalles, incluidas las propiedades del intervalo, como la etiqueta que estableció en el greetingpaso 7.