OpenTelemetry es una serie de herramientas, API y SDK que nos permite generar, recopilar y exportar datos de telemetría (métricas, registros y trazas) para analizar el comportamiento y rendimiento de una aplicación.

Veamos como podemos ponerlo en funcionamiento en .NET.

Para ello vamos a crear una API del proyecto estándar en .NET6: WebApplication1

Como podéis observar se trata de un ejemplo estándar de una Web API de .NET6.

Y añadimos las siguientes referencias:

Atención, a fecha de redacción de este artículo aun andaban en prerelease, pero es posible que ya estén en versión final.

Ahora lo que tenemos que hacer es añadir la el servicio en Program.cs:

using OpenTelemetry.Resources;
using OpenTelemetry.Trace;

var builder = WebApplication.CreateBuilder(args);


// Add services to the container.

builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

builder.Services.AddOpenTelemetryTracing(tracerProviderBuilder =>
{
    tracerProviderBuilder
        .SetResourceBuilder(ResourceBuilder.CreateDefault()
            .AddService(builder.Environment.ApplicationName))
        .AddAspNetCoreInstrumentation()
        .AddOtlpExporter(opts => { opts.Endpoint = new Uri("http://localhost:4317"); });
});

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();

app.UseAuthorization();

app.MapControllers();

app.Run();

Y en la documentación de Jaeger tenemos como poner en marcha una imagen de docker para nuestro test:

docker run -d --name jaeger \
  -e COLLECTOR_ZIPKIN_HOST_PORT=:9411 \
  -e COLLECTOR_OTLP_ENABLED=true \
  -p 6831:6831/udp \
  -p 6832:6832/udp \
  -p 5778:5778 \
  -p 16686:16686 \
  -p 4317:4317 \
  -p 4318:4318 \
  -p 14250:14250 \
  -p 14268:14268 \
  -p 14269:14269 \
  -p 9411:9411 \
  jaegertracing/all-in-one:1.37

Pero como tampoco necesitamos tanto, podemos dejarlo así:

docker run -d --name jaeger \
  -p 5778:5778 \
  -p 16686:16686 \
  -p 4317:4317 \
  -p 4318:4318 \
  -d --restart=unless-stopped jaegertracing/opentelemetry-all-in-one

Entramos en http://localhost:16686 para ver que Jaeger esta funcionando:

Cargamos nuestra API y lanzamos unos cuantos gets:

Ya podemos ver los resultados en Jaeger:

Y la magia de OpenTelemetry es esta, si no os gusta Jaeger y queréis usar una alternativa como SigNoz, solo tenemos que instalar la imagen como se cuenta en este documento.

Para Azure Monitor tenemos en Preview opciones de OTLP (OpenTelemetry Protocol):

En Azure debemos crear un Azure Application Insight y guardarnos la cadena de conexión (ver imagen superior).

Ahora añadimos las librerías de Azure.Monitor.OpenTelemetry y cambiamos el código:

En Azure debemos crear un Azure Application Insight:

using Azure.Monitor.OpenTelemetry.Exporter;
using OpenTelemetry.Resources;
using OpenTelemetry.Trace;

var builder = WebApplication.CreateBuilder(args);


// Add services to the container.

builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

builder.Services.AddOpenTelemetryTracing(tracerProviderBuilder =>
{
    tracerProviderBuilder
        .SetResourceBuilder(ResourceBuilder.CreateDefault()
            .AddService(builder.Environment.ApplicationName))
        .AddAspNetCoreInstrumentation()
        .AddAzureMonitorTraceExporter(o =>
        {
            o.ConnectionString = "[YOUR_INSTRUMENTATION_CONNECTIONSTRING]";
        });
        //.AddOtlpExporter(opts => { opts.Endpoint = new Uri("http://localhost:4317"); });
});

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();

Si lo deseas puedes exportar la información a Jaeger igualmente, pero veamos que sale tras lanzar unas cuantas veces el get del API:

Como podéis observar este protocolo nos permitirá conectar o desconectar con los sistemas de monitorización que más nos interese.