O que é o rastreamento distribuído e a correlação de telemetria?

Observação

A documentação a seguir depende da API clássica do Application Insights. O plano de longo prazo do Application Insights é coletar dados usando o OpenTelemetry. Para obter mais informações, confira Habilitar o OpenTelemetry do Azure Monitor para aplicativos .NET, Node.js, Python e Java.

Arquiteturas modernas de nuvem e microsserviços deram origem a serviços simples e implantáveis de forma independente que reduzem custos, aumentando a disponibilidade e a taxa de transferência. Contudo, eles também fizeram sistemas gerais mais difíceis de raciocinar e depurar. O rastreamento distribuído resolve esse problema fornecendo um criador de perfil de desempenho que funciona como pilhas de chamadas para arquiteturas de nuvem e microsserviços.

O Azure Monitor fornece duas experiências para consumir dados de rastreamento distribuídos: a exibição de diagnóstico da transação para uma única transação/solicitação e a exibição de mapa do aplicativo para mostrar como os sistemas interagem.

O Application Insights pode monitorar cada componente separadamente e detectar qual componente é responsável por falhas ou degradação de desempenho usando correlação de telemetria distribuída. Este artigo explica o modelo de dados, técnicas de propagação de contexto, protocolos e implementação de táticas de correlação em diferentes linguagens e plataformas usadas pelo Application Insights.

Habilitar o rastreamento distribuído

Para habilitar o rastreamento distribuído para um aplicativo, adicione o agente, o SDK ou a biblioteca corretos a cada serviço com base em sua linguagem de programação.

Habilitar pelo Application Insights por meio de instrumentação automática ou SDKs

Os SDKs e agentes do Application Insights para .NET, .NET Core, Java, Node.js e JavaScript oferecem suporte nativo ao rastreamento distribuído. As instruções para instalar e configurar cada SDK do Application Insights estão disponíveis para:

Com o SDK do Application Insights adequado instalado e configurado, as informações de rastreamento são coletadas automaticamente para estruturas, bibliotecas e tecnologias populares por coletores automáticos de dependência do SDK. A lista completa de tecnologias com suporte está disponível na Documentação de autocoleção de dependência.

Qualquer tecnologia também pode ser rastreada manualmente com uma chamada para TrackDependency sobre o TelemetryClient.

Habilitar via OpenTelemetry

O Application Insights agora dá suporte ao rastreamento distribuído por meio do OpenTelemetry. O OpenTelemetry fornece uma instrumentação neutra de fornecedor para enviar rastreamentos, métricas e logs para o Application Insights. Inicialmente, a comunidade OpenTelemetry assumiu o rastreamento distribuído. As métricas e os logs ainda estão em andamento.

Uma história completa de observabilidade inclui todos os três pilares. Verifique o status de nossas ofertas baseadas em OpenTelemetry do Azure Monitor para ver as status mais recentes sobre o que está incluído, quais ofertas estão em disponibilidade geral e opções de suporte.

As páginas a seguir consistem em diretrizes por linguagem para habilitar e configurar as ofertas baseadas em OpenTelemetry da Microsoft. Mais importante, compartilhamos a funcionalidade disponível e as limitações de cada oferta para que você possa determinar se OpenTelemetry é ideal para seu projeto.

Habilitar por meio do OpenCensus

Além dos SDKs do Application Insights, o Application Insights também dá suporte ao rastreamento distribuído por meio do OpenCensus. O OpenCensus é uma distribuição única de bibliotecas de software livre e independente de fornecedor, que tem como objetivo fornecer coleta de métricas e rastreamento distribuído para os serviços. Ele também permite que a comunidade de software livre habilite o rastreamento distribuído com tecnologias populares, como Redis, Memcached ou MongoDB. A Microsoft colabora no OpenCensus com vários outros parceiros de monitoramento e de nuvem.

Para obter mais informações sobre o OpenCensus para Python, consulte Configurar o Azure Monitor para seu aplicativo Python.

O site do OpenCensus mantém a documentação de referência da API para Python, Go e diversos guias para usar o OpenCensus.

Modelo de dados para correlação de telemetria

O Application Insights define um modelo de dados para correlação de telemetria distribuída. Para associar a telemetria à operação lógica, cada item de telemetria tem um campo de contexto chamado operation_Id. Cada item de telemetria no rastreamento distribuído compartilha esse identificador. Portanto, mesmo com a perda de telemetria de uma única camada, você ainda pode associar a telemetria relatada por outros componentes.

Uma operação lógica distribuída normalmente consiste de um conjunto de operações menores, que são solicitações processadas por um dos componentes. A Telemetria da solicitação define essas operações. Toda telemetria de solicitação tem seu próprio id que a identifica de modo exclusivo e global. E todos os itens de telemetria (como rastreamentos e exceções) associados a essa solicitação devem definir o operation_parentId para o valor de id da solicitação.

A Telemetria de dependência representa todas as operações de saída, como uma chamada HTTP para outro componente. Ela também define sua própria id que é globalmente única. A telemetria de solicitação, iniciada por essa chamada de dependência, usa este id como operation_parentId.

Você pode compilar um modo de exibição de operação lógica distribuída usando operation_Id, operation_parentId e request.id com dependency.id. Esses campos também definem a ordem de causalidade das chamadas de telemetria.

Em um ambiente de microsserviços, os rastreamentos de componentes podem ir para itens de armazenamento diferentes. Todo componente pode ter sua própria cadeia de conexão no Application Insights. Para obter a telemetria para a operação lógica, o Application Insights consulta dados de cada item de armazenamento.

Quando o número de itens de armazenamento for grande, você precisa de uma dica sobre onde procurar em seguida. O modelo de dados do Application Insights define dois campos para resolver esse problema: request.source e dependency.target. O primeiro campo identifica o componente que iniciou a solicitação de dependência. O segundo campo identifica qual componente retornou a resposta da chamada de dependência.

Para obter informações sobre como consultar várias instâncias diferentes usando a expressão de consulta app, confira a expressão app() na consulta do Azure Monitor.

Exemplo

Vamos examinar um exemplo. Vejamos um exemplo de um aplicativo chamado Preços de ações, que mostra o preço de mercado atual de uma ação usando uma API externa chamada Ações. O aplicativo Preços de ações tem uma página chamada Ações que o navegador da Web do cliente abre usando GET /Home/Stock. O aplicativo consulta a API Ações usando uma chamada HTTP GET /api/stock/value.

Você pode analisar a telemetria resultante executando uma consulta:

(requests | union dependencies | union pageViews)
| where operation_Id == "STYz"
| project timestamp, itemType, name, id, operation_ParentId, operation_Id

Nos resultados, todos os itens de telemetria compartilham a raiz operation_Id. Quando uma chamada Ajax é feita da página, uma nova ID exclusiva (qJSXU) é atribuída à telemetria de dependência e a ID de pageView é usada como operation_ParentId. A solicitação do servidor, em seguida, usa a ID do Ajax como operation_ParentId.

itemType name ID operation_ParentId operation_Id
pageView Página de ações STYz STYz
dependência GET /Home/Stock qJSXU STYz STYz
solicitação GET Home/Stock KqKwlrSt9PA= qJSXU STYz
dependência GET /api/stock/value bBrf2L7mm2g= KqKwlrSt9PA= STYz

Quando a chamada GET /api/stock/value é feita para um serviço externo, você precisa saber a identidade daquele servidor para que possa definir o campo dependency.target adequadamente. Quando o serviço externo não for compatível com o monitoramento, target será definido como o nome do host do serviço. Um exemplo é stock-prices-api.com. No entanto, se o serviço se identifica retornando um cabeçalho HTTP predefinido, target contém a identidade do serviço que permite que o Application Insights crie um rastreamento distribuído ao consultar a telemetria desse serviço.

Cabeçalhos de correlação usando o W3C TraceContext

O Application Insights está fazendo a transição para o W3C TraceContext, que define:

  • traceparent: carrega a ID globalmente exclusiva da operação e o identificador exclusivo da chamada.
  • tracestate: carrega o contexto específico do sistema de rastreamento.

A versão mais recente do SDK do Application Insights dá suporte ao protocolo Trace-Context, mas talvez seja necessário aceitá-lo. (A compatibilidade com versões anteriores com o protocolo de correlação anterior com suporte pelo SDK do Application Insights é mantida.)

O protocolo HTTP de correlação, também chamado Request-Id, está sendo preterido. Esse protocolo define dois cabeçalhos:

  • Request-Id: carrega a ID globalmente exclusiva da chamada.
  • Correlation-Context: carrega a coleção de pares nome-valor das propriedades de rastreamento distribuído.

O Application Insights também define a extensão para o protocolo HTTP de correlação. Ele usa pares nome-valor de Request-Context para propagar a coleção de propriedades usadas pelo computador chamado ou chamador imediato. O SDK do Application Insights usa esse cabeçalho para definir os campos dependency.target e request.source.

Os modelos de dados do W3C Trace-Context e do Application Insights são mapeados da seguinte maneira:

Application Insights W3C TraceContext
Id de Request e Dependency parent-id
Operation_Id trace-id
Operation_ParentId parent-id do intervalo pai desse intervalo. Esse campo deve estar vazio se for um intervalo raiz.

Para saber mais, confira o Modelo de dados de telemetria do Application Insights.

Habilitar suporte a rastreamento distribuído do W3C para aplicativos .NET

O rastreamento distribuído baseado em W3C TraceContext é habilitado por padrão em todos os SDKs recentes do .NET Framework/.NET Core, em conjunto com a compatibilidade com o protocolo de Solicitação-Id herdados.

Habilitar suporte a rastreamento distribuído do W3C para aplicativos Java

Agente Java 3.0

O agente Java 3.0 dá suporte ao W3C pronto para uso, sem necessidade de configuração adicional.

Java SDK

  • Configuração de entrada

    Para aplicativos Java EE, adicione o seguinte à marca <TelemetryModules> no ApplicationInsights.xml:

    <Add type="com.microsoft.applicationinsights.web.extensibility.modules.WebRequestTrackingTelemetryModule>
       <Param name = "W3CEnabled" value ="true"/>
       <Param name ="enableW3CBackCompat" value = "true" />
    </Add>
    

    Para aplicativos Spring Boot, adicione estas propriedades:

    • azure.application-insights.web.enable-W3C=true
    • azure.application-insights.web.enable-W3C-backcompat-mode=true
  • Configuração de saída

    Adicione o seguinte código ao AI-Agent.xml:

    <Instrumentation>
      <BuiltIn enabled="true">
        <HTTP enabled="true" W3C="true" enableW3CBackCompat="true"/>
      </BuiltIn>
    </Instrumentation>
    

    Observação

    o modo de compatibilidade com versões anteriores está habilitado por padrão e o parâmetro enableW3CBackCompat é opcional. Use-o somente quando quiser desativar a compatibilidade com versões anteriores.

    O ideal é desativar esse modo quando todos os seus serviços forem atualizados para versões mais recentes de SDKs que suportem o protocolo W3C. É altamente recomendável que você mude para os SDKs mais novos assim que possível.

É importante verificar se ambas as configurações de entrada e saída são exatamente as mesmas.

Habilitar suporte a rastreamento distribuído do W3C para aplicativos Web

Esse recurso é habilitado por padrão para JavaScript e os cabeçalhos são incluídos automaticamente quando o domínio da página de hospedagem é o mesmo que o domínio para o qual as solicitações são enviadas (por exemplo, a página de hospedagem é example.com e as solicitações do Ajax são enviadas para example.com). Para alterar o modo de rastreamento distribuído, use o distributedTracingModecampo de configuração. O AI_AND_W3C é fornecido por padrão para compatibilidade com versões anteriores com qualquer serviço herdado instrumentado pelo Application Insights.

Se as solicitações XMLHttpRequest ou Fetch Ajax forem enviadas para um host de domínio diferente, incluindo subdomínios, os cabeçalhos de correlação não serão incluídos por padrão. Para habilitar esse recurso, defina o enableCorsCorrelationcampo de configuração como true. Se você definir enableCorsCorrelation como true, todas as solicitações XMLHttpRequest e Fetch Ajax incluirão os cabeçalhos de correlação. Como resultado, se o aplicativo no servidor que está sendo chamado não der suporte ao cabeçalho traceparent, a solicitação poderá falhar, dependendo se o navegador/versão puder validar a solicitação com base em quais cabeçalhos o servidor aceita. Você pode usar o correlationHeaderExcludedDomainscampo de configuração para excluir o domínio do servidor da injeção de cabeçalho de correlação entre componentes. Por exemplo, você pode usar correlationHeaderExcludedDomains: ['*.auth0.com'] para excluir cabeçalhos de correlação de solicitações enviadas ao provedor de identidade Auth0.

Importante

Para ver todas as configurações necessárias para habilitar a correlação, consulte a documentação de correlação do JavaScript.

Correlação de telemetria no OpenCensus Python

O OpenCensus Python dá suporte ao W3C Trace-Context sem exigir configuração adicional.

Para uma referência, você pode encontrar o modelo de dados OpenCensus em nesta página do GitHub.

Correlação de solicitação de entrada

O OpenCensus Python correlaciona os cabeçalhos Trace-Context W3C das solicitações de entrada para os intervalos gerados a partir das próprias solicitações. O OpenCensus faz a correlação automaticamente com integrações nessas estruturas de aplicativo Web populares: Flask, Django e Pyramid. Você só precisa preencher os cabeçalhos Trace-Context W3C com o formato correto e enviá-los com a solicitação.

Explore este aplicativo Flask de exemplo. Instale o Flask, o OpenCensus e as extensões do Flask e do Azure.


pip install flask opencensus opencensus-ext-flask opencensus-ext-azure

Você precisa adicionar sua cadeia de conexão do Application Insights à variável de ambiente.

APPLICATIONINSIGHTS_CONNECTION_STRING=<appinsights-connection-string>

Aplicativo Flask de Exemplo

from flask import Flask
from opencensus.ext.azure.trace_exporter import AzureExporter
from opencensus.ext.flask.flask_middleware import FlaskMiddleware
from opencensus.trace.samplers import ProbabilitySampler

app = Flask(__name__)
middleware = FlaskMiddleware(
    app,
    exporter=AzureExporter(
        connection_string='<appinsights-connection-string>', # or set environment variable APPLICATION_INSIGHTS_CONNECTION_STRING
    ), 
    sampler=ProbabilitySampler(rate=1.0),
)

@app.route('/')
def hello():
    return 'Hello World!'

if __name__ == '__main__':
    app.run(host='localhost', port=8080, threaded=True)

Esse código executa um aplicativo Flask de exemplo em seu computador local, seguindo a porta 8080. Para correlacionar o contexto de rastreamento, você envia uma solicitação ao ponto de extremidade. Neste exemplo, você pode usar um curl comando:

curl --header "traceparent: 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01" localhost:8080

Ao examinar o formato de cabeçalho do Trace-Context, você pode derivar as seguintes informações:

version: 00

trace-id: 4bf92f3577b34da6a3ce929d0e0e4736

parent-id/span-id: 00f067aa0ba902b7

trace-flags: 01

Se você examinar a entrada de solicitação que foi enviada para o Azure Monitor, poderá ver os campos preenchidos com as informações do cabeçalho de rastreamento. Encontre esses dados em Logs (Análise) no recurso Application Insights do Azure Monitor.

Screenshot that shows Request telemetry in Logs (Analytics).

O campo id está no formato <trace-id>.<span-id>, em que o trace-id é tirado do cabeçalho de rastreamento que foi passado na solicitação e o span-id é uma matriz de 8 bytes gerada para esse intervalo.

O campo operation_ParentId está no formato <trace-id>.<parent-id>, em que trace-id e parent-id são tirados do cabeçalho de rastreamento que foi informado na solicitação.

Correlação de logs

O OpenCensus Python permite que você correlacione os logs adicionando uma ID de rastreamento, uma ID de extensão e um sinalizador de amostragem aos registros de log. Você adiciona esses atributos instalando a integração de logdo OpenCensus. Os atributos a seguir são adicionados aos objetos LogRecord do Python: traceId, spanId e traceSampled (aplicável somente para agentes criados após a integração).

Instalar a integração do registro em log do OpenCensus:

python -m pip install opencensus-ext-logging

Aplicativo de exemplo

import logging

from opencensus.trace import config_integration
from opencensus.trace.samplers import AlwaysOnSampler
from opencensus.trace.tracer import Tracer

config_integration.trace_integrations(['logging'])
logging.basicConfig(format='%(asctime)s traceId=%(traceId)s spanId=%(spanId)s %(message)s')
tracer = Tracer(sampler=AlwaysOnSampler())

logger = logging.getLogger(__name__)
logger.warning('Before the span')
with tracer.span(name='hello'):
    logger.warning('In the span')
logger.warning('After the span')

Quando esse código é executado, o seguinte é impresso no console:

2019-10-17 11:25:59,382 traceId=c54cb1d4bbbec5864bf0917c64aeacdc spanId=0000000000000000 Before the span
2019-10-17 11:25:59,384 traceId=c54cb1d4bbbec5864bf0917c64aeacdc spanId=70da28f5a4831014 In the span
2019-10-17 11:25:59,385 traceId=c54cb1d4bbbec5864bf0917c64aeacdc spanId=0000000000000000 After the span

Observe que há um spanId presente para a mensagem de log que está dentro do intervalo. O spanId é o mesmo que pertence ao intervalo nomeado hello.

Você pode exportar os dados de log usando AzureLogHandler. Para obter mais informações, confira Configurar Azure Monitor para seu aplicativo Python.

Também podemos passar informações de rastreamento de um componente para outro para uma correlação adequada. Por exemplo, considere um cenário em que há dois componentes module1 e module2. O módulo 1 chama funções no módulo 2. Para obter logs do module1 e do module2 em um único rastreamento, podemos usar a seguinte abordagem:

# module1.py
import logging

from opencensus.trace import config_integration
from opencensus.trace.samplers import AlwaysOnSampler
from opencensus.trace.tracer import Tracer
from module_2 import function_1

config_integration.trace_integrations(["logging"])
logging.basicConfig(
    format="%(asctime)s traceId=%(traceId)s spanId=%(spanId)s %(message)s"
)
tracer = Tracer(sampler=AlwaysOnSampler())

logger = logging.getLogger(__name__)
logger.warning("Before the span")

with tracer.span(name="hello"):
    logger.warning("In the span")
    function_1(logger, tracer)
logger.warning("After the span")
# module_2.py
import logging

from opencensus.trace import config_integration
from opencensus.trace.samplers import AlwaysOnSampler
from opencensus.trace.tracer import Tracer

config_integration.trace_integrations(["logging"])
logging.basicConfig(
    format="%(asctime)s traceId=%(traceId)s spanId=%(spanId)s %(message)s"
)
logger = logging.getLogger(__name__)
tracer = Tracer(sampler=AlwaysOnSampler())


def function_1(logger=logger, parent_tracer=None):
    if parent_tracer is not None:
        tracer = Tracer(
            span_context=parent_tracer.span_context,
            sampler=AlwaysOnSampler(),
        )
    else:
        tracer = Tracer(sampler=AlwaysOnSampler())

    with tracer.span("function_1"):
        logger.info("In function_1")

Correlação de telemetria em .NET

A correlação é tratada por padrão ao integrar um aplicativo. Nenhuma ação especial é necessária.

O runtime do .NET dá suporte ao distribuído com a ajuda de Activity e DiagnosticSource

O Application Insights SDK do .NET usa DiagnosticSource e Activity para coletar e correlacionar telemetria.

Correlação de telemetria no Java

O agente Java dá suporte à correlação automática de telemetria. Ele preenche automaticamente operation_id para toda a telemetria (como rastreamentos, exceções e eventos personalizados) emitida dentro do escopo de uma solicitação. Também propaga os cabeçalhos de correlação que foram descritos anteriormente para as chamadas de serviço a serviço, via HTTP, se o agente do SDK do Java estiver configurado.

Observação

O agente Java do Application Insights coleta automaticamente solicitações e dependências para JMS, Kafka, Netty/Webfbfbf e muito mais. Para o SDK do Java, somente chamadas feitas via Apache HttpClient têm suporte para o recurso de correlação. Atualmente, a propagação automática de contexto entre tecnologias de mensagens, como Kafka, RabbitMQ e Barramento de Serviço do Microsoft Azure não tem suporte no SDK.

Para coletar telemetria personalizada, você precisa instrumentar o aplicativo com o SDK do Java 2.6.

Nomes de função

Convém personalizar a maneira como os nomes de componentes são exibidos no Mapa do Aplicativo. Para fazer isso, você pode definir manualmente cloud_RoleName seguindo uma das seguintes ações:

  • Para o Java do Application Insights, defina o nome da função de nuvem da seguinte forma:

    {
      "role": {
        "name": "my cloud role name"
      }
    }
    

    Você também pode definir o nome da função de nuvem usando a variável de ambiente APPLICATIONINSIGHTS_ROLE_NAME.

  • Com o SDK do Java 2.5.0 e posterior do Application Insights, você pode especificar o cloud_RoleName adicionando <RoleName> ao seu arquivo ApplicationInsights.xml:

    Screenshot that shows Application Insights overview and connection string.

    <?xml version="1.0" encoding="utf-8"?>
    <ApplicationInsights xmlns="http://schemas.microsoft.com/ApplicationInsights/2013/Settings" schemaVersion="2014-05-30">
       <ConnectionString>InstrumentationKey=00000000-0000-0000-0000-000000000000</ConnectionString>
       <RoleName>** Your role name **</RoleName>
       ...
    </ApplicationInsights>
    
  • Se você usar o Spring Boot com o Iniciador do Spring Boot do Application Insights, defina seu nome personalizado para o aplicativo no arquivo application.properties:

    spring.application.name=<name-of-app>

Você também pode definir o nome da função de nuvem, por meio da variável de ambiente ou da propriedade do sistema. Confira Configurando o nome da função de nuvem para obter detalhes.

Próximas etapas