Compartir a través de


Ejemplo: Uso de OpenTelemetry con OTLP y el panel de Aspire independiente

Se trata de una serie de ejemplos que reflejan la observabilidad de .NET con OpenTelemetry.

Además de ser una parte estándar de .NET Aspire, el panel de Aspire está disponible como un contenedor de Docker independiente, que ofrece una telemetría de puntos de conexión de OTLP que se puede enviar, y permite ver los registros, las métricas y los seguimientos. El uso del panel de esta manera no tiene ninguna dependencia en .NET Aspire; la telemetría se puede visualizar en cualquier aplicación que lo envíe a través de OTLP. Funciona igualmente bien para aplicaciones escritas en Java, GoLang, Python, etc., siempre que puedan enviar su telemetría a un punto de conexión de OTLP.

Al usar el panel de Aspire, se deben realizar menos pasos de configuración que al usar soluciones de código abierto como Prometheus, Grafana y Jaeger, pero a diferencia de estas herramientas, el panel de Aspire está pensado como una herramienta de visualización para desarrolladores y no como método de supervisión de la 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. Agregar métricas y definiciones de actividad

El código siguiente define una nueva métrica (greetings.count) para el número de veces que se ha llamado a la API y un nuevo origen de actividad (Otel.Example).

// 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");

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

Inserte lo 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.

4. Referencia a los paquetes de OpenTelemetry

Use el Administrador de paquetes NuGet o la línea de comandos para agregar los siguientes paquetes NuGet:

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

Nota

Use las versiones más recientes, ya que las API de OTel evolucionan constantemente.

5. Configuración de OpenTelemetry con los proveedores correctos

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

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

var otel = builder.Services.AddOpenTelemetry();

// 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 provides by ASP.NET Core in .NET 8
    metrics.AddMeter("Microsoft.AspNetCore.Hosting");
    metrics.AddMeter("Microsoft.AspNetCore.Server.Kestrel");
});

// 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);
});

// Export OpenTelemetry data via OTLP, using env vars for the configuration
var OtlpEndpoint = builder.Configuration["OTEL_EXPORTER_OTLP_ENDPOINT"];
if (OtlpEndpoint != null)
{
    otel.UseOtlpExporter();
}

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

  • Agrega un proveedor de OTel a ILogger para recopilar entradas de registro.
  • Configura métricas, registra proveedores de instrumentación y medidores para ASP.NET y nuestro medidor personalizado.
  • Configura el seguimiento, el registro de proveedores de instrumentación y nuestro ActivitySource personalizado.

Después, registra el exportador de OTLP mediante env vars para configurarlo.

6. Configuración de variables de entorno de OTLP

El exportador de OTLP se puede configurar a través de API en el código, pero lo normal es configurarlo a través de variables de entorno. Agregue lo siguiente a AppSettings.Development.json

"OTEL_EXPORTER_OTLP_ENDPOINT": "http://localhost:4317",
"OTEL_SERVICE_NAME": "OTLP-Example"

Puede agregar variables de entorno adicionales para el exportador de OTLP de .NET o variables de OTel comunes, como OTEL_RESOURCE_ATTRIBUTES para definir atributos de recursos.

Nota:

Un problema común es mezclar AppSettings.json y AppSettings.Development.json, si este último está presente, se usará cuando se pulse F5 en Visual Studio y se ignorará cualquier configuración en AppSettings.json.

7. Inicio del contenedor del panel de 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 está protegido con autenticación que precisa de un token para iniciar sesión. El token se ve en el resultado final al ejecutar el contenedor.

[Panel de Aspire]

Copie la dirección URL que se muestra y reemplácela por 0.0.0.0 localhost, por ejemplo, http://localhost:18888/login?t=123456780abcdef123456780, y ábrala en el navegador; también puede pegar la clave después de /login?t= cuando se abra el cuadro de diálogo de inicio de sesión. El token cambiará cada vez que inicie el contenedor.

8. Ejecución el proyecto

Ejecute el proyecto y acceda a la API con el explorador o curl.

curl -k http://localhost:7275

Cada vez que solicite la página, incrementará el recuento del número de saludos que se han realizado.

8.1 Salida del registro

Las instrucciones de registro del código se generan mediante ILogger. De forma predeterminada, el proveedor de consola está habilitado para que la salida se dirija a la consola.

Existen un par de opciones para la salida de registros desde .NET:

  • La salida de stdout y stderr se redirige a archivos de registro por sistemas de contenedores como Kubernetes.
  • Con bibliotecas de registro que se integrarán con ILogger, se incluyen Serilog o NLog.
  • Uso de proveedores de registro para OTel, como OTLP. La sección de registro en el código del paso 5 permite agregar el proveedor OTel.

Los registros aparecen en el panel como registros estructurados: las propiedades establecidas en el mensaje de registro se extraen como campos en la entrada de registros.

Registros en el panel independiente

8.2 Visualización de las métricas

En el panel de Aspire aparecen las métricas por recurso (el recurso es la forma que OTel usa cuando se refiere a orígenes de telemetría, como un proceso). Cuando se selecciona un recurso, en el panel saldrá cada métrica enviada al punto de conexión de OTLP por el recurso. La lista de métricas es dinámica y cambia a medida que se reciben nuevas métricas.

Métricas en el panel independiente

La vista de las métricas dependerá del tipo de métrica que se use:

  • Las cifras aparecerán directamente.
  • Los histogramas que realizan un seguimiento de un valor por solicitud, como un intervalo de tiempo o los bytes enviados por solicitud, se recopilan en una serie de segmentos. En el panel se creará una gráfica de los percentiles P50, P90 y P99. Los resultados del histograma pueden incluir ejemplos, que son puntos de datos autónomos, junto con el trace/spanId de esa solicitud. Se representan como puntos en el gráfico. Si selecciona uno, se accederá al seguimiento correspondiente para que pueda ver lo que ha ocurrido para que se genere ese valor. Esto es útil para diagnosticar valores atípicos.
  • Las métricas pueden incluir dimensiones, que son pares clave-valor asociados a valores concretos. Los valores se agrupan por dimensión. Con las listas desplegables que aparecen en la vista, puede filtrar los resultados para examinar dimensiones específicas, como las solicitudes de solo GET o las de una ruta de dirección URL específica en ASP.NET.

8.3 Visualización del seguimiento

La vista de seguimiento mostrará una lista de seguimientos: cada seguimiento es un conjunto de actividades que comparten el mismo traceId. Se realiza un seguimiento del trabajo con intervalos que representan una unidad de trabajo. Al procesar una solicitud de ASP.NET, se creará un intervalo. La creación de una solicitud HttpClient será un intervalo. Mediante el seguimiento del elemento primario del intervalo, se puede visualizar una jerarquía de intervalos. Al recopilar intervalos de un recurso (proceso), se realiza un seguimiento del trabajo que se produce en una serie de servicios. Las solicitudes HTTP tienen un encabezado que se usa para pasar el traceId y spanId principal al siguiente servicio. Cada recurso debe recopilar los datos de telemetría y enviarlos al mismo recopilador. Después, se agrupa y presenta la jerarquía de intervalos.

Seguimientos en el panel independiente

En el panel aparecerá una lista de seguimientos con una información resumida. Siempre que se vean intervalos con un nuevo traceId, se generará una fila en la tabla. Al hacer clic en la vista, aparecerán todos los intervalos del seguimiento.

Intervalos en el panel independiente

Al seleccionar un intervalo saldrán sus detalles, incluidas las propiedades del intervalo, como la etiqueta greeting creada en el paso 3.