Nota
O acesso a esta página requer autorização. Podes tentar iniciar sessão ou mudar de diretório.
O acesso a esta página requer autorização. Podes tentar mudar de diretório.
Este exemplo usa Prometheus para coleta de métricas, Grafana para criar um painel e Jaeger para mostrar rastreamento distribuído.
1. Crie o projeto
Crie um projeto de API Web simples usando o modelo ASP.NET Core Empty no Visual Studio ou o seguinte comando da CLI do .NET:
dotnet new web
2. Adicione métricas e definições de atividade
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 (OtPrGrYa.Example).
// Custom metrics for the application
var greeterMeter = new Meter("OtPrGrYa.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("OtPrGrJa.Example");
3. Criar um ponto de extremidade da API
app.MapGet("/", SendGreeting);
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
A definição da API não usa nada específico para o OpenTelemetry. Ele usa as APIs do .NET para observabilidade.
4. Faça referência aos pacotes OpenTelemetry
Use o Gerenciador de Pacotes NuGet ou a linha de comando para adicionar os seguintes pacotes NuGet:
dotnet add package OpenTelemetry.Exporter.Console
dotnet add package OpenTelemetry.Exporter.OpenTelemetryProtocol
dotnet add package OpenTelemetry.Exporter.Prometheus.AspNetCore --prerelease
dotnet add package OpenTelemetry.Exporter.Zipkin
dotnet add package OpenTelemetry.Extensions.Hosting
dotnet add package OpenTelemetry.Instrumentation.AspNetCore
dotnet add package OpenTelemetry.Instrumentation.Http
5. Configure o OpenTelemetry com os provedores corretos
var tracingOtlpEndpoint = builder.Configuration["OTLP_ENDPOINT_URL"];
var otel = builder.Services.AddOpenTelemetry();
// Configure OpenTelemetry Resources with the application name
otel.ConfigureResource(resource => resource
.AddService(serviceName: builder.Environment.ApplicationName));
// Add Metrics for ASP.NET Core and our custom metrics and export to Prometheus
otel.WithMetrics(metrics => metrics
// Metrics provider from OpenTelemetry
.AddAspNetCoreInstrumentation()
.AddMeter(greeterMeter.Name)
// Metrics provides by ASP.NET Core in .NET 8
.AddMeter("Microsoft.AspNetCore.Hosting")
.AddMeter("Microsoft.AspNetCore.Server.Kestrel")
// Metrics provided by System.Net libraries
.AddMeter("System.Net.Http")
.AddMeter("System.Net.NameResolution")
.AddPrometheusExporter());
// Add Tracing for ASP.NET Core and our custom ActivitySource and export to Jaeger
otel.WithTracing(tracing =>
{
tracing.AddAspNetCoreInstrumentation();
tracing.AddHttpClientInstrumentation();
tracing.AddSource(greeterActivitySource.Name);
if (tracingOtlpEndpoint != null)
{
tracing.AddOtlpExporter(otlpOptions =>
{
otlpOptions.Endpoint = new Uri(tracingOtlpEndpoint);
});
}
else
{
tracing.AddConsoleExporter();
}
});
Esse código usa a instrumentação ASP.NET Core para obter métricas e atividades do ASP.NET Core. Ele também registra os Metrics e ActivitySource provedores para métricas e rastreamento, respectivamente.
O código usa o exportador Prometheus para métricas, que usa ASP.NET Core para hospedar o ponto de extremidade, então você também precisa adicionar:
// Configure the Prometheus scraping endpoint
app.MapPrometheusScrapingEndpoint();
6. Execute o projeto
Execute o projeto e, em seguida, acesse a API com o navegador ou curl.
curl -k http://localhost:7275
Cada vez que solicita a página, ela incrementa a contagem do número de cumprimentos feitos. Pode aceder ao endpoint das métricas usando a mesma URL base, com o caminho /metrics.
6.1 Saída de log
As instruções de log do código são saídas usando ILogger. Por padrão, o Provedor de Console é habilitado para que a saída seja direcionada para o console.
Existem algumas opções sobre como os logs podem ser retirados do .NET:
-
stdoutestderra saída é redirecionada para arquivos de log por sistemas de contêiner, como o Kubernetes. - Usar bibliotecas de registo que se integram com o ILogger. Estas bibliotecas incluem Serilog e NLog.
- Usar fornecedores de registo para OTel, como OTLP, ou o exportador Azure Monitor mostrado mais adiante.
6.2 Acesse as métricas
Você pode acessar as métricas usando o /metrics endpoint.
curl -k https://localhost:7275/
Hello World!
curl -k https://localhost:7275/metrics
# TYPE greetings_count counter
# HELP greetings_count Counts the number of greetings
greetings_count 1 1686894204856
# TYPE current_connections gauge
# HELP current_connections Number of connections that are currently active on the server.
current_connections{endpoint="127.0.0.1:7275"} 1 1686894204856
current_connections{endpoint="[::1]:7275"} 0 1686894204856
current_connections{endpoint="[::1]:5212"} 1 1686894204856
...
A saída de métricas é um instantâneo das métricas no momento em que o ponto de extremidade é solicitado. Os resultados são fornecidos em formato de exposição Prometheus, que é legível por humanos, mas melhor compreendido por Prometheus. Esse tema é abordado na próxima etapa.
6.3 Aceder ao rastreio
Se você olhar para o console para o servidor, verá a saída do exportador de rastreamento de console, que produz as informações em um formato legível por humanos. Isso deve mostrar duas atividades, uma do seu costume ActivitySourcee outra do ASP.NET Core:
Activity.TraceId: 2e00dd5e258d33fe691b965607b91d18
Activity.SpanId: 3b7a891f55b97f1a
Activity.TraceFlags: Recorded
Activity.ParentSpanId: 645071fd0011faac
Activity.ActivitySourceName: OtPrGrYa.Example
Activity.DisplayName: GreeterActivity
Activity.Kind: Internal
Activity.StartTime: 2023-06-16T04:50:26.7675469Z
Activity.Duration: 00:00:00.0023974
Activity.Tags:
greeting: Hello World!
Resource associated with Activity:
service.name: OTel-Prometheus-Grafana-Jaeger
service.instance.id: e1afb619-bc32-48d8-b71f-ee196dc2a76a
telemetry.sdk.name: opentelemetry
telemetry.sdk.language: dotnet
telemetry.sdk.version: 1.5.0
Activity.TraceId: 2e00dd5e258d33fe691b965607b91d18
Activity.SpanId: 645071fd0011faac
Activity.TraceFlags: Recorded
Activity.ActivitySourceName: Microsoft.AspNetCore
Activity.DisplayName: /
Activity.Kind: Server
Activity.StartTime: 2023-06-16T04:50:26.7672615Z
Activity.Duration: 00:00:00.0121259
Activity.Tags:
net.host.name: localhost
net.host.port: 7275
http.method: GET
http.scheme: https
http.target: /
http.url: https://localhost:7275/
http.flavor: 1.1
http.user_agent: curl/8.0.1
http.status_code: 200
Resource associated with Activity:
service.name: OTel-Prometheus-Grafana-Jaeger
service.instance.id: e1afb619-bc32-48d8-b71f-ee196dc2a76a
telemetry.sdk.name: opentelemetry
telemetry.sdk.language: dotnet
telemetry.sdk.version: 1.5.0
A primeira é a atividade personalizada interna que você criou. O segundo é criado por ASP.NET para a solicitação e inclui tags para as propriedades da solicitação HTTP. Verás que ambos têm o mesmo TraceId, que identifica uma única transação. Num sistema distribuído, o ID de traço pode ser usado para correlacionar os traços de cada serviço envolvido numa transação. Os IDs são transmitidos como cabeçalhos HTTP. ASP.NET Core atribui um TraceId se nenhum estiver presente quando recebe uma solicitação.
HttpClient Inclui os cabeçalhos por padrão em solicitações de saída. Cada atividade tem um SpanId, que é a combinação de TraceId e SpanId que identificam de forma única cada atividade. A Greeter atividade é parentada à atividade HTTP por meio de seu ParentSpanId, que mapeia para a SpanId atividade HTTP.
Em um estágio posterior, você alimentará esses dados no Jaeger para visualizar os rastreamentos distribuídos.
7. Colete métricas com Prometheus
Prometheus é um sistema de banco de dados de coleta de métricas, agregação e séries temporais. Você o configura com os pontos de extremidade métricos para cada serviço e ele periodicamente raspa os valores e os armazena em seu banco de dados de séries temporais. Em seguida, você pode analisá-los e processá-los conforme necessário.
Os dados de métricas expostos no formato Prometheus são um instantâneo point-in-time das métricas do processo. Cada vez que um pedido é feito ao endpoint das métricas, este reporta os valores atuais. Embora os valores atuais sejam interessantes, eles se tornam mais valiosos quando comparados aos valores históricos para ver tendências e detetar se os valores são anômalos. Comumente, os serviços têm picos de uso com base na hora do dia ou eventos mundiais, como uma onda de compras de fim de ano. Ao comparar os valores com tendências históricas, pode detetar se são anormais ou se uma métrica está a piorar lentamente ao longo do tempo.
O processo não armazena nenhum histórico desses instantâneos métricos. Adicionar essa capacidade ao processo pode exigir muitos recursos. Além disso, em um sistema distribuído, você geralmente tem várias instâncias de cada nó, portanto, deseja ser capaz de coletar as métricas de todas elas e, em seguida, agregar e comparar com seus valores históricos.
7.1 Instalar e configurar o Prometheus
Faça o download do https://prometheus.io/download/ Prometheus para a sua plataforma e extraia o conteúdo do download.
Olha para o topo da saída do teu servidor em execução para obter o número de porta do endpoint HTTP. Por exemplo:
info: Microsoft.Hosting.Lifetime[14]
Now listening on: https://localhost:7275
info: Microsoft.Hosting.Lifetime[14]
Now listening on: http://localhost:5212
Modifique o arquivo de configuração do Prometheus YAML para especificar a porta para seu ponto de extremidade de raspagem HTTP e defina um intervalo de raspagem menor. Por exemplo:
scrape_configs:
# The job name is added as a label `job=<job_name>` to any timeseries scraped from this config.
- job_name: "prometheus"
# metrics_path defaults to '/metrics'
# scheme defaults to 'http'.
scrape_interval: 1s # poll very quickly for a more responsive demo
static_configs:
- targets: ["localhost:5212"]
Inicie o Prometheus e procure na saída a porta em que ele está sendo executado, normalmente 9090:
>prometheus.exe
...
ts=2023-06-16T05:29:02.789Z caller=web.go:562 level=info component=web msg="Start listening for connections" address=0.0.0.0:9090
Abra este URL no seu navegador. Na interface do Prometheus, agora deves conseguir consultar as tuas métricas. Use o botão realçado na imagem a seguir para abrir o explorador de métricas, que mostra todas as métricas disponíveis.
Selecione a greetings_count métrica para ver um gráfico de valores.
8. Use o Grafana para criar um painel de métricas
Grafana é um produto de dashboarding que pode criar dashboards e alertas com base no Prometheus ou noutras fontes de dados.
Baixe e instale a versão OSS do Grafana https://grafana.com/oss/grafana/ seguindo as instruções para sua plataforma. Uma vez instalado, o Grafana é normalmente executado na porta 3000, por isso abra http://localhost:3000 no seu navegador. Terás de iniciar sessão; o nome de utilizador e a palavra-passe padrão são ambos admin.
No menu hambúrguer, escolhe ligações e depois insere o texto prometheus para selecionar o tipo de endpoint. Selecione Criar uma fonte de dados Prometheus para adicionar uma nova fonte de dados.
Defina a URL do servidor Prometheus para http://localhost:9090/, alterando a porta conforme aplicável.
Selecione Save & Test para verificar a configuração.
Depois de receber uma mensagem de sucesso, você pode configurar um painel. Selecione o link para construir um dashboard apresentado na janela pop-up da mensagem de sucesso.
Selecione Adicionar uma visualização e, em seguida, escolha a fonte de dados Prometheus que você acabou de adicionar como a fonte de dados.
O designer do painel do painel deve aparecer. Na metade inferior da tela, você pode definir a consulta.
Selecione a greetings_count métrica e, em seguida, selecione Executar consultas para ver os resultados.
Com o Grafana, você pode projetar painéis sofisticados que rastrearão qualquer número de métricas.
Cada métrica no .NET pode ter dimensões adicionais, que são pares chave-valor que podem ser usados para particionar os dados. Todas as métricas ASP.NET apresentam uma série de dimensões aplicáveis ao contador. Por exemplo, o current-requests contador de Microsoft.AspNetCore.Hosting tem as seguintes dimensões:
| Atributo | Tipo | Descrição | Exemplos | Presença |
|---|---|---|---|---|
method |
string |
Método de solicitação HTTP. |
GET; POST; HEAD |
Sempre |
scheme |
string |
O esquema de URI que identifica o protocolo usado. |
http; https |
Sempre |
host |
string |
Nome do servidor HTTP local que recebeu a solicitação. | localhost |
Sempre |
port |
int |
Porta do servidor HTTP local que recebeu a solicitação. | 8080 |
Adicionado se não for padrão (80 para http ou 443 para https) |
Os gráficos em Grafana são geralmente particionados com base em cada combinação única de dimensões. As dimensões podem ser usadas nas consultas Grafana para filtrar ou agregar os dados. Por exemplo, se você criar um gráfico current_requests, verá valores particionados com base em cada combinação de dimensões. Para filtrar com base apenas no host, adicione uma operação de e use Sum como o valor do host rótulo.
9. Rastreamento distribuído com Jaeger
Na etapa 6, você viu que as informações de rastreamento distribuído estavam sendo expostas ao console. Esta informação rastreia unidades de trabalho com atividades. Algumas atividades são criadas automaticamente pela plataforma, como a de ASP.NET para representar o tratamento de uma solicitação, e bibliotecas e código do aplicativo também podem criar atividades. O exemplo das saudações tem uma Greeter atividade. As atividades são correlacionadas usando as TraceIdtags , SpanId, e ParentId .
Cada processo em um sistema distribuído produz seu próprio fluxo de informações de atividade e, como métricas, você precisa de um sistema para coletar, armazenar e correlacionar as atividades para poder visualizar o trabalho feito para cada transação. Jaeger é um projeto de código aberto para permitir essa coleção e visualização.
Faça o download do arquivo de distribuição binária mais recente do Jaeger para sua plataforma em https://www.jaegertracing.io/download/.
Em seguida, extraia o download para um local de fácil acesso. Execute o executável jaeger-all-in-one(.exe ):
./jaeger-all-in-one --collector.otlp.enabled
Examine a saída do console para encontrar a porta onde ele está ouvindo o tráfego OTLP via gRPC. Por exemplo:
{"level":"info","ts":1686963686.3854616,"caller":"otlpreceiver@v0.78.2/otlp.go:83","msg":"Starting GRPC server","endpoint":"0.0.0.0:4317"}
Essa saída informa que está ouvindo no 0.0.0.0:4317, para que você possa configurar essa porta como o destino para seu exportador OTLP.
Abra o AppSettings.json arquivo para o nosso projeto e adicione a seguinte linha, alterando a porta, se aplicável.
"OTLP_ENDPOINT_URL" : "http://localhost:4317/"
Reinicie o processo de rececionista para que ele possa pegar a alteração de propriedade e começar a direcionar as informações de rastreamento para Jaeger.
Agora, você deve ser capaz de ver a interface do usuário do Jaeger em http://localhost:16686/ a partir de um navegador da web.
Para ver uma lista de rastreamentos, selecione OTel-Prometheus-grafana-Jaeger na lista suspensa Serviço . A seleção de um rastreamento deve mostrar um gráfico de gantt das atividades como parte desse rastreamento. Clicar em cada uma das operações mostra mais detalhes sobre a atividade.
Em um sistema distribuído, você deseja enviar rastreamentos de todos os processos para a mesma instalação do Jaeger para que ele possa correlacionar as transações em todo o sistema.
Você pode tornar seu aplicativo um pouco mais interessante fazendo com que ele faça chamadas HTTP para si mesmo.
Adicione uma
HttpClientfábrica à aplicação:builder.Services.AddHttpClient();Adicionar um novo endpoint para efetuar chamadas aninhadas de cumprimentos:
app.MapGet("/NestedGreeting", SendNestedGreeting);Implemente o ponto de extremidade para que ele faça chamadas HTTP que também possam ser rastreadas. Neste caso, chama-se de volta a si próprio num ciclo artificial (aplicável apenas a cenários de demonstração):
async Task SendNestedGreeting(int nestlevel, ILogger<Program> logger, HttpContext context, IHttpClientFactory clientFactory) { // Create a new Activity scoped to the method using var activity = greeterActivitySource.StartActivity("GreeterActivity"); if (nestlevel <= 5) { // Log a message logger.LogInformation("Sending greeting, level {nestlevel}", nestlevel); // Increment the custom counter countGreetings.Add(1); // Add a tag to the Activity activity?.SetTag("nest-level", nestlevel); await context.Response.WriteAsync($"Nested Greeting, level: {nestlevel}\r\n"); if (nestlevel > 0) { var request = context.Request; var url = new Uri($"{request.Scheme}://{request.Host}{request.Path}?nestlevel={nestlevel - 1}"); // Makes an http call passing the activity information as http headers var nestedResult = await clientFactory.CreateClient().GetStringAsync(url); await context.Response.WriteAsync(nestedResult); } } else { // Log a message logger.LogError("Greeting nest level {nestlevel} too high", nestlevel); await context.Response.WriteAsync("Nest level too high, max is 5"); } }
Isso resulta em um gráfico mais interessante com uma forma de pirâmide para as solicitações, já que cada nível aguarda a resposta da chamada anterior.