Conceitos de rastreamento distribuído .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árias máquinas ou processos. Consulte a Visão geral do rastreamento distribuído para obter informações gerais sobre onde o rastreamento distribuído é útil.
Vestígios e Atividades
Cada vez que uma nova solicitação é recebida por um aplicativo, ela pode ser associada a um rastreamento. Em componentes de aplicativo escritos em .NET, as unidades de trabalho em um rastreamento são representadas por instâncias de System.Diagnostics.Activity e o rastreamento como um todo forma uma árvore dessas Atividades, potencialmente abrangendo muitos processos distintos. A primeira atividade criada para uma nova solicitação forma a raiz da árvore de rastreamento e rastreia a duração total e o tratamento bem-sucedido/falhado da solicitação. As atividades infantis podem ser criadas opcionalmente para subdividir o trabalho em diferentes etapas que podem ser acompanhadas individualmente. Por exemplo, dada uma Atividade que rastreou uma solicitação HTTP de entrada específica em um servidor Web, atividades filhas podem ser criadas para rastrear cada uma das consultas de banco de dados necessárias para concluir a solicitação. Isso permite que a duração e o sucesso de cada consulta sejam registrados de forma independente. As atividades podem registrar outras informações para cada unidade de trabalho, como OperationNamepares nome-valor chamados Tags, e Events. O nome identifica o tipo de trabalho que está sendo executado, as tags podem registrar parâmetros descritivos do trabalho e os eventos são um mecanismo de registro simples para registrar mensagens de diagnóstico com carimbo de data/hora.
Nota
Outro nome comum da indústria para unidades de trabalho em um traço distribuído são 'Spans'. O .NET adotou o termo "Atividade" há muitos anos, antes que o nome "Span" estivesse bem estabelecido para este conceito.
IDs de atividade
As relações pai-filho entre Atividades na árvore de rastreamento distribuída são estabelecidas usando IDs exclusivas. . A implementação do rastreamento distribuído da NET suporta dois esquemas de ID: o padrão W3C TraceContext, que é o padrão no .NET 5+, e uma convenção .NET mais antiga chamada 'Hierarchical' que está disponível para compatibilidade com versões anteriores. Activity.DefaultIdFormat controla qual esquema de identificação é usado. No padrão TraceContext do W3C, a cada rastreamento é atribuído um rastreio de 16 bytes globalmente exclusivo (Activity.TraceId), e a cada atividade dentro do rastreamento é atribuído um span-id exclusivo de 8 bytes (Activity.SpanId). Cada atividade registra o trace-id, seu próprio span-id e o span-id de seu pai (Activity.ParentSpanId). Como os rastreamentos distribuídos podem rastrear o trabalho através dos limites do processo, as Atividades pai e filho podem não estar no mesmo processo. A combinação de um trace-id e um span-id pai pode identificar exclusivamente a atividade pai globalmente, independentemente do processo em que ela reside.
Activity.DefaultIdFormat controla qual formato de ID é usado para iniciar novos rastreamentos, mas, por padrão, adicionar uma nova Atividade a um rastreamento existente usa qualquer formato que a Atividade pai esteja usando. A configuração Activity.ForceDefaultIdFormat como true substitui esse comportamento e cria todas as novas Atividades com o DefaultIdFormat, mesmo quando o pai usa um formato de ID diferente.
Iniciar e parar Atividades
Cada thread em um processo pode ter um objeto Activity correspondente que rastreia o trabalho que ocorre nesse thread, acessível via Activity.Current. A atividade atual flui automaticamente ao longo de todas as chamadas síncronas em um thread e segue chamadas assíncronas que são processadas em threads diferentes. Se a Atividade A for a atividade atual em um thread e o código iniciar uma nova Atividade B, B se tornará a nova atividade atual nesse thread. Por padrão, a atividade B também tratará a atividade A como sua empresa-mãe. Quando a Atividade B for interrompida posteriormente, a atividade A será restaurada como a Atividade atual no thread. Quando uma atividade é iniciada, ela captura a hora atual como o Activity.StartTimeUtc. Quando para, Activity.Duration é calculado como a diferença entre a hora atual e a hora de início.
Coordene-se entre os limites do processo
Para acompanhar o trabalho através dos limites do processo, os IDs pai de atividade precisam ser transmitidos pela rede para que o processo de recebimento possa criar Atividades que se referem a eles. Ao usar o formato W3C TraceContext ID, o .NET também usa os cabeçalhos HTTP recomendados pelo padrão para transmitir essas informações. Ao usar o formato de ID, o Hierarchical .NET usa um cabeçalho HTTP de ID de solicitação personalizado para transmitir a ID. Ao contrário de muitos outros tempos de execução de linguagem, as bibliotecas de caixa de entrada do .NET, como o servidor Web ASP.NET e o System.Net.Http, entendem nativamente como decodificar e codificar IDs de atividade em mensagens HTTP. O tempo de execução também entende como fluir a ID por meio de chamadas síncronas e assíncronas. Isso significa que os aplicativos .NET que recebem e emitem mensagens HTTP participam do fluxo de IDs de rastreamento distribuído automaticamente, sem codificação especial pelo desenvolvedor do aplicativo ou dependências de bibliotecas de terceiros. Bibliotecas de terceiros podem adicionar suporte para transmitir IDs em protocolos de mensagem não-HTTP ou suportar convenções de codificação personalizadas para HTTP.
Recolha de vestígios
O código instrumentado pode criar Activity objetos como parte de um rastreamento distribuído, mas as informações nesses objetos precisam ser transmitidas e serializadas em um armazenamento persistente centralizado para que todo o rastreamento possa ser revisado posteriormente de forma útil. Há várias bibliotecas de coleção de telemetria que podem fazer essa tarefa, como Application Insights, OpenTelemetry ou uma biblioteca fornecida por um fornecedor de telemetria ou APM de terceiros. Como alternativa, os desenvolvedores podem criar sua própria coleção de telemetria de atividade personalizada usando System.Diagnostics.ActivityListener ou System.Diagnostics.DiagnosticListener. O ActivityListener suporta a observação de qualquer atividade, independentemente de o desenvolvedor ter algum conhecimento prévio sobre ela. Isso torna o ActivityListener uma solução de uso geral simples e flexível. Por outro lado, o uso do DiagnosticListener é um cenário mais complexo que requer que o código instrumentado aceite invocando DiagnosticSource.StartActivity e a biblioteca de coleções precisa saber as informações de nomenclatura exatas que o código instrumentado usou ao iniciá-lo. O uso de DiagnosticSource e DiagnosticListener permite que o criador e o ouvinte troquem objetos .NET arbitrários e estabeleçam convenções de passagem de informações personalizadas.
Amostragem
Para melhorar o desempenho em aplicativos de alta taxa de transferência, o rastreamento distribuído no .NET oferece suporte à amostragem apenas de um subconjunto de rastreamentos, em vez de gravar todos eles. Para atividades criadas com a API recomendada ActivitySource.StartActivity , as bibliotecas de coleta de telemetria podem controlar a amostragem com o retorno de ActivityListener.Sample chamada. A biblioteca de registro em log pode optar por não criar a Atividade, criá-la com o mínimo de informações necessárias para propagar IDs de rastreamento de distribuição ou preenchê-la com informações de diagnóstico completas. Essas escolhas compensam o aumento da sobrecarga de desempenho para aumentar a utilidade do diagnóstico. Atividades que são iniciadas usando o padrão mais antigo de invocação Activity.Activity e DiagnosticSource.StartActivity também podem oferecer suporte à amostragem do DiagnosticListener chamando pela primeira vez DiagnosticSource.IsEnabled. Mesmo ao capturar informações completas de diagnóstico, a implementação do .NET foi projetada para ser rápida - juntamente com um coletor eficiente, uma atividade pode ser criada, preenchida e transmitida em cerca de um microssegundo no hardware moderno. A amostragem pode reduzir o custo da instrumentação para menos de 100 nanossegundos para cada atividade que não é registrada.
Próximos passos
Para obter um código de exemplo para começar a usar o rastreamento distribuído em aplicativos .NET, consulte a Instrumentação de rastreamento distribuído.