Compartilhar via


Exemplo: Use o OpenTelemetry com OTLP e o painel autônomo do Aspire

Este é um de uma série de exemplos para ilustrar a observabilidade do .NET com o OpenTelemetry.

Além de ser uma parte padrão do .NET Aspire, o Aspire Dashboard está disponível como um contêiner docker autônomo, que fornece um endpoint OTLP para o qual a telemetria pode ser enviada e visualizará os logs, métricas e rastreamentos. Usar o painel dessa maneira não depende do .NET Aspire, ele visualizará a telemetria de qualquer aplicativo que envie telemetria via OTLP. Funciona igualmente bem para aplicativos escritos em Java, GoLang, Python etc. desde que possam enviar sua telemetria para um endpoint OTLP.

O uso do Aspire Dashboard tem menos etapas de configuração do que o uso de soluções de código aberto, como Prometheus, Grafana e Jaeger, mas, ao contrário dessas ferramentas, o Aspire Dashboard destina-se a ser uma ferramenta de visualização do desenvolvedor e não para monitoramento de produção.

1. Criar o projeto

Crie um projeto simples de API Web usando o modelo ASP.NET Core Vazio no Visual Studio ou o seguinte comando da CLI do .NET:

dotnet new web

2. Adicionar definições de métricas e atividades

O código a seguir define uma nova métrica (greetings.count) para o número de vezes que a API foi chamada e uma nova fonte de atividade (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. Criar um ponto de extremidade de API

Inserir o seguinte entre builder.Build(); e app.Run()

app.MapGet("/", SendGreeting);

Inserir a seguinte função no final do arquivo:

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!";
}

Observação

A definição de ponto de extremidade não usa nada específico para OpenTelemetry. Usa apenas as APIs do .NET para observabilidade.

4. Referenciar os pacotes do OpenTelemetry

Use o Gerenciador de Pacotes NuGet ou a linha de comando para adicionar os seguintes pacotes 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>

Observação

Use as versões mais recentes, pois as APIs do OTel estão em constante evolução.

5. Configurar o OpenTelemetry com os provedores corretos

Inserir o seguinte 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 o OpenTelemetry com as diferentes fontes de telemetria:

  • Ele adiciona um provedor OTel ao ILogger para coletar registros de log.
  • Ele configura métricas, registrando provedores de instrumentação e medidores para ASP.NET e nosso medidor personalizado.
  • Ele configura o rastreamento, o registro de provedores de instrumentação e nosso ActivitySource personalizado.

Em seguida, ele registra o exportador OTLP usando env vars para sua configuração.

6. Configurar variáveis ​​de ambiente OTLP

O exportador OTLP pode ser configurado por meio de APIs no código, mas é mais comum configurá-lo por meio de variáveis de ambiente. Adicione o seguinte a AppSettings.Development.json

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

Você pode adicionar variáveis de ambiente adicionais para o Exportador de OTLP do .NET ou variáveis OTel comuns, como OTEL_RESOURCE_ATTRIBUTES para definir atributos de recurso.

Observação

Uma pegadinha comum é misturar AppSettings.json e AppSettings.Development.json, se o último estiver presente, ele será usado quando você usar F5 no Visual Studio e todas as configurações em AppSettings.json serão ignoradas.

7. Inicie o contêiner do Aspire Dashboard

Use o docker para baixar e executar o contêiner de painéis.

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

Os dados exibidos no painel podem ser confidenciais. Por padrão, o painel é protegido com autenticação que requer um token para fazer login. O token é exibido na saída resultante ao executar o contêiner.

[Aspire Dashboard]

Copie o url mostrado e substitua 0.0.0.0 por localhost, por exemplo http://localhost:18888/login?t=123456780abcdef123456780 e abra-o em seu navegador, ou você também pode colar a chave depois /login?t= que a caixa de diálogo de login for exibida. O token será alterado sempre que você iniciar o contêiner.

8. Executar o projeto

Execute o projeto e acesse a API com o navegador ou curl.

curl -k http://localhost:7275

Sempre que você solicitar a página, ela incrementará a contagem do número de saudações que foram feitas.

8.1 Saída dos logs

As instruções de registro em log do código são geradas usando ILogger. Por padrão, o Provedor de Console está habilitado para que a saída seja direcionada para o console.

Há algumas opções de como os logs podem sair do .NET:

  • As saídas stdout e stderr são redirecionadas para arquivos de log por sistemas de contêiner, como o Kubernetes.
  • Usando bibliotecas de log que serão integradas ao ILogger, elas incluem Serilog ou NLog.
  • Usando provedores de log para OTel, como OTLP. A seção de log no código da etapa 5 adiciona o provedor OTel.

Os logs são mostrados no painel como logs estruturados - todas as propriedades definidas na mensagem de log são extraídas como campos no registro de log.

Logs no painel autônomo

8.2 Visualizando as métricas

O painel do Aspire mostra métricas por recurso (um recurso é a maneira OTel de falar sobre fontes de telemetria, como um processo). Quando um recurso é selecionado, o painel enumera cada métrica que foi enviada ao ponto de extremidade OTLP pelo recurso. A lista de métricas é dinâmica e será atualizada à medida que novas métricas forem recebidas.

Métricas no painel autônomo

A exibição das métricas dependerá do tipo de métrica que está sendo usada:

  • Os contadores serão mostrados diretamente.
  • Os histogramas que rastreiam um valor por solicitação, como um intervalo de tempo ou bytes enviados por solicitação, são coletados em uma série de buckets. O painel representará graficamente os percentis P50, P90 e P99. Os resultados do histograma podem incluir exemplares, que são pontos de dados individuais junto com o trace/spanId para essa solicitação. Estes serão mostrados como pontos no gráfico. Selecionar um navegará até o respectivo rastreamento para que você possa ver o que aconteceu para causar esse valor. Isso é útil para diagnosticar valores discrepantes.
  • As métricas podem incluir dimensões, que são pares de chave/valor associados a valores individuais. Os valores são agregados por dimensão. Usando as listas suspensas na exibição, você pode filtrar os resultados para examinar dimensões específicas, tais como apenas solicitações GET ou aquelas para uma rota de URL específica em ASP.NET.

8.3 Visualizando o rastreamento

A exibição de rastreamento mostrará uma lista de rastreamentos – cada rastreamento é um conjunto de atividades que compartilham o mesmo traceId. O trabalho é rastreado com intervalos que representam uma unidade de trabalho. O processamento de uma solicitação ASP.NET criará um intervalo. Fazer uma solicitação HttpClient será um intervalo. Ao rastrear o pai do intervalo, uma hierarquia de intervalos pode ser visualizada. Ao coletar intervalos de cada recurso (processo), rastreamos o trabalho que acontece em uma série de serviços. As solicitações HTTP têm um cabeçalho que é usado para passar o traceId e o spanId pai para o próximo serviço. Cada recurso precisa coletar telemetria e enviá-la para o mesmo coletor. Em seguida, ele agregará e apresentará uma hierarquia dos intervalos.

Rastreamentos no painel autônomo

O painel mostrará uma lista de rastreamentos com informações resumidas. Sempre que intervalos com um novo traceId forem vistos, eles obterão uma linha na tabela. Clicar em exibir mostrará todos os intervalos no rastreamento.

Extensões no painel autônomo

A seleção de um intervalo mostrará seus detalhes, incluindo quaisquer propriedades no intervalo, tais como a greeting tag que definimos na etapa 3.