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.
[]
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
estderr
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.
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.
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.
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.
A seleção de um intervalo mostrará seus detalhes, incluindo quaisquer propriedades no intervalo, tais como a greeting
tag que definimos na etapa 3.