Rastreamento distribuído em bibliotecas de System.Net
O Rastreamento distribuído é uma técnica de diagnóstico que ajuda os engenheiros a localizar falhas e problemas de desempenho em aplicativos, especialmente aqueles que podem ser distribuídos em vários computadores ou processos. Essa técnica rastreia solicitações por meio de um aplicativo correlacionando o trabalho em conjunto feito por diferentes componentes e separando-o de outros trabalhos que o aplicativo pode estar fazendo para solicitações simultâneas. Por exemplo, uma solicitação para um serviço Web típico pode ser recebida primeiro por um balanceador de carga e, em seguida, encaminhada para um processo de servidor Web, que faz várias consultas para um banco de dados. O rastreamento distribuído permite que os engenheiros distinguem se alguma dessas etapas falhou e quanto tempo cada etapa demorou. Ele também pode registrar mensagens produzidas por cada etapa à medida que foi executada.
O sistema de rastreamento no .NET foi projetado para funcionar com o OpenTelemetry (OTel) e usa o OTel para exportar os dados para sistemas de monitoramento. O rastreamento no .NET é implementado utilizando as APIs de System.Diagnostics, em que uma unidade de trabalho é representada pela classe System.Diagnostics.Activity, que corresponde a um intervalo de OTel. O OpenTelemetry define um esquema de nomenclatura padrão em todo o setor para intervalos (atividades) juntamente com seus atributos (marcas), conhecidos como convenções semânticas. A telemetria do .NET usa convenções semânticas existentes sempre que possível.
Nota
Neste artigo, os termos intervalo e atividade são utilizados como sinônimos. No contexto do código .NET, eles se referem a uma instância de System.Diagnostics.Activity. Não confunda o intervalo de OTel com System.Span<T>.
Dica
Para obter uma lista abrangente de todas as atividades internas, juntamente com suas marcas/atributos, consulte Atividades internas no .NET.
Instrumentação
Para emitir rastreamentos, as bibliotecas de System.Net são instrumentadas com fontes de ActivitySource internas, que criam objetos Activity para rastrear o trabalho executado. As atividades somente serão criadas se houver ouvintes inscritos no ActivitySource.
A instrumentação interna evoluiu com versões do .NET.
- Nas versões 8 e anteriores do .NET, a instrumentação é limitada à criação de uma atividade de solicitação de cliente HTTP vazia. Isso significa que os usuários precisam contar com a biblioteca
OpenTelemetry.Instrumentation.Http
para preencher a atividade com as informações (por exemplo, tags) necessárias para emitir rastreamentos úteis. - O .NET 9 ampliou a instrumentação emitindo o nome, o status, as informações de exceção e as marcas mais importantes de acordo com as convenções semânticas de cliente HTTP do OTel na atividade de solicitação de cliente HTTP. Isso significa que, no .NET 9+, a dependência
OpenTelemetry.Instrumentation.Http
pode ser omitida, a menos que recursos mais avançados, como de enriquecimento, sejam necessários. - O .NET 9 também introduziu o rastreamento experimental de conexão, adicionando novas atividades às bibliotecas de
System.Net
, para dar suporte ao diagnóstico de problemas de conexão.
Coletar logs de System.Net
No nível mais baixo, a coleta de rastreamento é suportada por meio do método AddActivityListener, que registra objetos ActivityListener que contêm lógica definida pelo usuário.
No entanto, como desenvolvedor de aplicativos, você provavelmente prefere contar com o ecossistema avançado criado com base nos recursos fornecidos pelo OpenTelemetry .NET SDK para coletar, exportar e monitorar rastreamentos.
- Para obter uma compreensão fundamental sobre a coleta de rastreamentos com o OTel, consulte nosso guia sobre coleta de rastreamentos usando o OpenTelemetry.
- Para a coleta e monitoramento do rastreamento de tempo de produção, é possível usar o OpenTelemetry com Prometheus, Grafana e Jaeger ou com o Azure Monitor e o Application Insights. No entanto, essas ferramentas são bastante complexas e podem ser inconvenientes de usar em tempo de desenvolvimento.
- Para a coleta e monitoramento do rastreamento de tempo de desenvolvimento, recomendamos usar o .NET Aspire, que fornece uma maneira simples, mas extensível, de iniciar o rastreamento distribuído em seu aplicativo e diagnosticar problemas localmente.
- Também é possível reutilizar o projeto de padrões de serviço do Aspire sem a orquestração Aspire Essa é uma maneira útil de introduzir e configurar o rastreamento e as métricas do OpenTelemetry em seus projetos de ASP.NET.
Coletar rastreamentos com o .NET Aspire
Uma maneira simples de coletar rastreamentos e métricas em aplicativos ASP.NET é usar .NET Aspire. O .NET Aspire é um conjunto de extensões para .NET para facilitar a criação e o trabalho com aplicativos distribuídos. Um dos benefícios de usar o .NET Aspire é que a telemetria é interna, usando as bibliotecas OpenTelemetry para .NET.
Os modelos de projeto padrão do .NET Aspire contêm um projeto ServiceDefaults
. Cada serviço na solução .NET Aspire tem uma referência ao projeto Padrões de Serviço. Isso é utilizado pelos serviços preparar e configurar o OTel.
O modelo de projeto de padrões de serviço inclui os pacotes de instrumentação OTel SDK, ASP.NET, HttpClient e Runtime. Esses componentes de instrumentação são configurados no arquivo Extensions.cs. Para dar suporte à visualização de telemetria no Painel do Aspire, o projeto Padrões de Serviço também inclui o exportador OTLP por padrão.
O painel do Aspire foi projetado para trazer a observação de telemetria para o ciclo de depuração local, o que permite que os desenvolvedores garantam que os aplicativos estejam produzindo telemetria. A visualização de telemetria também ajuda a diagnosticar esses aplicativos localmente. Ser capaz de observar as chamadas entre serviços é útil tanto no momento da depuração quanto na produção. O painel do .NET Aspire é iniciado automaticamente quando você F5 o projeto AppHost
do Visual Studio ou dotnet run
o projeto AppHost
pela linha de comando.
Para obter mais informações sobre o .NET Aspire, consulte:
Reutilizar projeto de padrões de serviço sem a orquestração do .NET Aspire
O projeto de padrões de serviço do Aspire proporciona uma maneira fácil de configurar o OTel para projetos ASP.NET, mesmo sem que se esteja usando o restante do .NET Aspire, como o AppHost para orquestração. O projeto de Padrões de Serviço está disponível como um modelo de projeto por meio do Visual Studio ou dotnet new
. Ele configura o OTel e define o exportador OTLP. Em seguida, você pode usar as variáveis de ambiente OTel para configurar o ponto de extremidade OTLP para o qual enviar telemetria e fornecer as propriedades de recurso para o aplicativo.
As etapas para usar ServiceDefaults fora do .NET Aspire são:
Adicione o projeto ServiceDefaults à solução usando Adicionar Novo Projeto no Visual Studio ou use
dotnet new
:dotnet new aspire-servicedefaults --output ServiceDefaults
Faça referência ao projeto ServiceDefaults do aplicativo ASP.NET. No Visual Studio, selecione Adicionar>Referência de Projeto e selecione o projeto ServiceDefaults."
Chame a função de configuração do OpenTelemetry
ConfigureOpenTelemetry()
como parte da inicialização do configurador de aplicativos.var builder = WebApplication.CreateBuilder(args) builder.ConfigureOpenTelemetry(); // Extension method from ServiceDefaults. var app = builder.Build(); app.MapGet("/", () => "Hello World!"); app.Run();
Para obter um passo a passo completo, consulte Exemplo: Usar o OpenTelemetry com OTLP e o painel autônomo do Aspire.
Rastreamento experimental de conexão
Ao solucionar problemas HttpClient
ou gargalos, pode ser crucial verificar onde o tempo está sendo utilizado ao enviar solicitações HTTP. Geralmente, o problema ocorre durante o estabelecimento da conexão HTTP, que normalmente se divide em resolução de DNS, conexão TCP e handshake TLS.
O .NET 9 introduziu o rastreamento experimental de conexão adicionando um intervalo de HTTP connection setup
com três intervalos filho que representam as fases DNS, TCP e TLS do estabelecimento da conexão. A parte HTTP do rastreamento de conexão é implementada no SocketsHttpHandler, o que significa que o modelo de atividade deve respeitar o comportamento de pool de conexões subjacente.
Nota
Em SocketsHttpHandler, conexões e solicitações têm ciclos de vida independentes. Uma conexão em pool pode durar muito tempo e atender a muitas solicitações. Ao fazer uma solicitação, se não houver nenhuma conexão disponível imediatamente no pool de conexões, a solicitação será adicionada a uma fila de solicitação para aguardar uma conexão disponível. Não há nenhuma relação direta entre solicitações de espera e conexões. O processo de conexão pode ter sido iniciado quando outra conexão ficou disponível para uso, caso em que a conexão liberada é usada. Como resultado, o intervalo de HTTP connection setup
não é modelado como filho do intervalo de HTTP client request
e, em vez disso, são utilizados links de intervalo.
O .NET 9 introduziu os seguintes intervalos para habilitar a coleta de informações detalhadas de conexão:
Nome | ActivitySource | Descrição |
---|---|---|
HTTP wait_for_connection |
Experimental.System.Net.Http.Connections |
Um intervalo filho ao intervalo de HTTP client request , que representa o período de tempo que a solicitação aguarda uma conexão disponível na fila de solicitações. |
HTTP connection_setup |
Experimental.System.Net.Http.Connections |
Representa o estabelecimento da conexão HTTP. Um intervalo raiz de rastreamento separado com seu próprio TraceId . Os intervalos de HTTP client request podem conter links para HTTP connection_setup . |
DNS lookup |
Experimental.System.Net.NameResolution |
Pesquisa DNS executada pela classe Dns. |
socket connect |
Experimental.System.Net.Sockets |
Estabelecimento de uma conexão de Socket. |
TLS handshake |
Experimental.System.Net.Security |
Handshake de cliente ou servidor TLS executado por SslStream. |
Nota
Os nomes de ActivitySource
correspondentes começam com o prefixo Experimental
, pois esses intervalos podem ser alterados em versões futuras à medida que aprendemos mais sobre como eles funcionam bem na produção.
Esses intervalos são detalhados demais para serem usados 24x7 em cenários de produção com cargas de trabalho muito altas – eles produzem ruído e normalmente esse nível de instrumentação não é necessário. No entanto, se você estiver tentando diagnosticar problemas de conexão ou obter uma compreensão mais profunda de como a latência de rede e conexão está afetando seus serviços, eles fornecem insights difíceis de coletar por outros meios.
Quando o ActivitySource Experimental.System.Net.Http.Connections
estiver habilitado, o intervalo de HTTP client request
contém um link para o intervalo de HTTP connection_setup
correspondente à conexão que atende à solicitação. Como uma conexão HTTP pode ter uma vida útil longa, isso pode resultar em muitos links para o intervalo de conexão de cada atividade de solicitação. Algumas ferramentas de monitoramento de APM seguem de forma agressiva os links entre intervalos, para criar suas exibições, portanto, incluir esse intervalo pode causar problemas quando as ferramentas não tiverem sido projetadas para lidar com um grande número de links.
O diagrama a seguir ilustra o comportamento dos intervalos e sua relação:
Passo a passo: usando o rastreamento de conexão experimental no .NET 9
Este passo a passo usa um aplicativo de projeto inicial do .NET Aspire 9 para demonstrar o rastreamento da conexão, mas deveria ser fácil configurá-lo também com outras ferramentas de monitoramento. A etapa principal é habilitar os ActivitySources.
Crie um aplicativo inicial .NET Aspire 9 usando
dotnet new
:dotnet new aspire-starter-9 --output ConnectionTracingDemo
Ou no Visual Studio:
Abra
Extensions.cs
no projetoServiceDefaults
e edite o métodoConfigureOpenTelemetry
, adicionando o ActivitySources para conexão no retorno de chamada da configuração de rastreamento:.WithTracing(tracing => { tracing.AddAspNetCoreInstrumentation() // Instead of using .AddHttpClientInstrumentation() // .NET 9 allows to add the ActivitySources directly. .AddSource("System.Net.Http") // Add the experimental connection tracking ActivitySources using a wildcard. .AddSource("Experimental.System.Net.*"); });
Inicie a solução. Isso deveria abrir o painel do .NET Aspire.
Navegue até a página de previsão do tempo do aplicativo
webfrontend
, para gerar uma solicitaçãoHttpClient
destinada aapiservice
.Retorne ao painel e navegue até a página Rastreamentos. Abra o rastreamento de
webfrontend: GET /weather
.
Quando solicitações HTTP são feitas com a instrumentação de conexão habilitada, você deve ver as seguintes alterações nos intervalos de solicitação do cliente:
- Se for necessário estabelecer uma conexão ou se o aplicativo estiver aguardando uma conexão do pool de conexões, será mostrado um intervalo adicional de
HTTP wait_for_connection
, que representa o atraso pela espera do estabelecimento da conexão. Isso ajuda a entender os atrasos entre a solicitaçãoHttpClient
sendo feita no código e o momento em que o processamento da solicitação realmente é iniciado. Na imagem anterior:- O intervalo selecionado é a solicitação HttpClient.
- O intervalo abaixo representa o tempo gasto pela solicitação aguardando que uma conexão seja estabelecida.
- O último intervalo em amarelo é do destino que processa a solicitação.
- O span HttpClient terá um link para o span
HTTP connection_setup
, que representa a atividade de criar a conexão HTTP usada pela solicitação.
Conforme mencionado anteriormente, o intervalo de HTTP connection_setup
é um intervalo separado com seu próprio TraceId
, pois seu tempo de vida é independente de cada solicitação individual do cliente. Normalmente esse intervalo tem os intervalos filhos DNS lookup
, (TCP) socket connect
e TLS client handshake
.
Enriquecimento
Em alguns casos, é necessário aprimorar a funcionalidade existente de rastreamento de System.Net
. Normalmente, isso significa injetar etiquetas/atributos adicionais nas atividades internas. Isso é denominado enriquecimento.
API de enriquecimento na biblioteca de instrumentação OpenTelemetry
Para adicionar marcas/atributos adicionais à atividade de solicitação de cliente HTTP, a abordagem mais simples é usar as APIs de enriquecimento HttpClient
da biblioteca de instrumentação HttpClient e HttpWebRequest do OpenTelemetry. Isso exige assumir uma dependência no pacote OpenTelemetry.Instrumentation.Http
.
Enriquecimento manual
É possível implementar o enriquecimento da atividade de HTTP client request
manualmente. Para isso, você precisa acessar Activity.Current no código que está em execução no escopo da atividade de solicitação, antes que a atividade seja concluída. Isso pode ser feito implementando um IObserver<DiagnosticListener>
e assinando-o para AllListeners, para obter retornos de chamada para quando a atividade de rede estiver ocorrendo. Na verdade, é assim que a biblioteca de instrumentação HttpClient e HttpWebRequest do OpenTelemetry é implementada. Para obter um exemplo de código, consulte o código de assinatura em DiagnosticSourceSubscriber.cs
e a implementação subjacente em HttpHandlerDiagnosticListener.cs para o qual as notificações são delegadas.
Precisa de mais rastreamento?
Se você tiver sugestões para outras informações úteis que possam ser expostas por meio de rastreamento, crie um problema de dotnet/runtime.