OpenTelemetry e Azure Monitor para IA: traces, spans, Application Insights e KQL
Instrumente um pipeline RAG distribuído, propague o contexto W3C, exporte telemetria confiável, controle a amostragem e diagnostique latência com Mapa do Aplicativo, detalhes da transação e KQL.
Tempo de estudo sugerido: 125 minutos • Nível intermediário • Reescrita autoral completa com versão resumida de cada tópico, avaliação comentada e laboratório Python guiado
Por João Ricardo Dutra••Conteúdo autoral completo
1. Cenário e objetivos de aprendizagem
Uma solução RAG de suporte ao cliente reúne um de , um serviço de embeddings, um serviço de pesquisa vetorial e um orquestrador de LLM. A maioria das respostas chega em dois segundos, mas algumas ultrapassam dez. Cada serviço produz um diferente, portanto os horários isolados não demonstram onde o tempo foi consumido. A meta é manter o p95 abaixo de três segundos e enxergar a integridade de todos os serviços em uma única visão.
Explicar observabilidade e o papel de , métricas e .
Instrumentar Python com a Distro OpenTelemetry do .
Criar spans personalizados e correlacionados para operações de IA.
Exportar e verificar telemetria no .
Usar diagnósticos visuais e KQL para localizar latência, falhas e padrões de cargas de IA.
Resumo rápido
O desafio não é a falta de isolados, mas a ausência de uma narrativa correlacionada para a requisição que atravessa todo o RAG.
2. Observabilidade e os três pilares
Observabilidade é a capacidade de deduzir o estado interno de um sistema a partir dos sinais que ele emite. Em IA distribuída, latência, erros ou perda de qualidade podem surgir na chamada ao modelo, na recuperação, no acesso a dados ou na orquestração.
Três perspectivas complementares
Sinal
Pergunta respondida
Exemplo em IA
Métricas
O comportamento está mudando ao longo do tempo?
Volume, taxa de erro, processados e duração p95.
distribuídos
Onde uma requisição gastou tempo ou falhou?
Caminho completo → embedding → pesquisa → LLM.
Por que uma operação se comportou assim?
Motivo de uma repetição, detalhe de validação ou erro do modelo.
Métricas revelam que algo mudou, localizam a etapa e fornecem o detalhe local. O foco deste capítulo é rastreamento, mas o diagnóstico confiável combina os três.
Resumo rápido
Métricas detectam, localizam e explicam; nenhum dos três substitui os demais.
3. OpenTelemetry como padrão neutro
OpenTelemetry é uma estrutura de observabilidade aberta e neutra mantida no ecossistema da Cloud Native Computing Foundation. As definem como o código produz telemetria; os SDKs implementam processamento, lotes, amostragem e recursos; bibliotecas de instrumentação observam ; e exportadores serializam sinais para um .
Instrumente a lógica uma vez com estáveis.
Direcione sinais ao , Jaeger, Prometheus, Grafana ou outro destino compatível sem reescrever os spans de negócio.
Use instrumentação automática para protocolos comuns e manual para a semântica da IA.
Mantenha o modelo de telemetria independente de um único fornecedor de análise.
OpenTelemetry separa a produção dos sinais do destino; a distribuição do empacota os componentes usados com .
Resumo rápido
OpenTelemetry padroniza a produção e o transporte da telemetria sem prender o código ao de análise.
4. , spans, hierarquia e contexto
Um é o registro de ponta a ponta de uma operação distribuída. Cada span representa uma unidade de trabalho nomeada e temporizada. Ele contém o ID comum à transação, seu span ID, o ID do span pai quando existe, nome, horários inicial e final, atributos e status.
As relações pai-filho formam uma árvore. A requisição no é a raiz; embedding, pesquisa e modelo são descendentes. O OpenTelemetry transporta essa relação entre chamadas com TraceContext. O cabeçalho traceparent segue versão--id-parent-span-id-, por exemplo 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01. O 01 final indica amostragem.
Cada serviço conserva o ID, cria seu span ID e registra o chamador como pai para reconstruir a cascata.
Resumo rápido
O ID correlaciona a jornada, os IDs de span preservam causalidade e traceparent leva o contexto entre serviços.
5. Correspondência com
Terminologia e armazenamento
OpenTelemetry
Python
Tracer
.get_tracer("nome")
Fonte de instrumentação; não cria uma linha por si só.
Span SERVER ou CONSUMER
SpanKind.SERVER ou CONSUMER
Solicitação: no esquema clássico ou AppRequests no .
Span , INTERNAL ou PRODUCER
SpanKind correspondente
Dependência: dependencies ou AppDependencies.
ID
span.get_span_context().trace_id
operation_Id / OperationId.
Span ID e pai
span_id e contexto pai
id e operation_ParentId.
Atributos
span.set_attribute()
customDimensions / Properties.
, exceções e métricas
, record_exception e Meter
/AppTraces, exceptions/AppExceptions e customMetrics/AppMetrics.
Consultas abertas a partir do recurso do costumam usar os nomes clássicos apresentados nos exemplos. Transformações no nível do usam as tabelas App*. operation_Id é a chave de correlação no esquema clássico.
Resumo rápido
O tipo do span determina solicitação ou dependência, enquanto operation_Id conecta todos os itens da transação.
6. Escolha entre instrumentação automática e no código
Abordagens
Abordagem
Quando usar
Compensação
Instrumentação automática do host
Cargas compatíveis no , Functions ou VMs que precisam de uma linha de base sem alterar o código.
Pouco esforço, porém menor controle sobre contexto de negócio.
Distro dentro da aplicação
Serviços de IA que precisam expor embedding, recuperação, prompt, ou modelo.
Exige código e governança, mas libera spans, atributos e amostragem personalizados.
A Distro OpenTelemetry do reúne do Python, exportadores, detectores de recursos e instrumentações compatíveis. Spans manuais complementam — não repetem — a telemetria , de , bancos, SDKs e .
Resumo rápido
Use automação como base e a Distro incorporada quando o precisar expressar operações de negócio da IA.
7. Instale e conecte a Distro Python
Instale -monitor-opentelemetry e execute configure_azure_monitor() uma vez na inicialização. A função configura os provedores globais de , métrica e . Em produção, armazene a cadeia de conexão na variável APPLICATIONINSIGHTS_CONNECTION_STRING, nunca no repositório.
pip install azure-monitor-opentelemetry
from azure.monitor.opentelemetry import configure_azure_monitor
from opentelemetry import trace
# Read APPLICATIONINSIGHTS_CONNECTION_STRING from the environment.
configure_azure_monitor()
tracer = trace.get_tracer("rag-api")
A cadeia identifica o ponto de e o recurso. O argumento connection_string explícito prevalece sobre a variável equivalente; variáveis de amostragem constituem uma exceção documentada e prevalecem sobre argumentos de amostragem. Não registre esse valor.
Resumo rápido
Uma chamada inicial estabelece o ; a cadeia fica na configuração da implantação, fora do código.
8. Entenda a coleta automática
Cobertura comum em Python
Origem
Telemetria coletada
Flask, Django e FastAPI
Rotas recebidas como solicitações, com duração e status; integrações compatíveis capturam exceções não tratadas.
, urllib e urllib3
Dependências de saída.
psycopg2
Operações e tempo de PostgreSQL.
Bibliotecas de cliente do do
Chamadas a serviços compatíveis do .
do Python
Registros conectados ao OpenTelemetry.
A automação elimina repetição, mas não sabe que uma função monta um prompt ou que result_count mede a recuperação. Adicione spans manuais onde houver valor operacional e evite duplicar spans ou de banco já produzidos.
Resumo rápido
A coleta automática fornece estrutura; spans personalizados fornecem significado de IA.
9. Identifique cada serviço com atributos de recurso
Quando vários serviços enviam dados ao mesmo , service.name cria um nome de função de nuvem para cada componente. service. agrupa a solução e service.instance.id diferencia réplicas. Sem nomes estáveis, telemetria distinta aparece em um único nó.
from azure.monitor.opentelemetry import configure_azure_monitor
from opentelemetry.sdk.resources import Resource
resource = Resource.create({
"service.name": "embedding-service",
"service.namespace": "support-rag",
"service.instance.id": "embedding-01",
})
configure_azure_monitor(resource=resource)
O nome da função combina service. e service.name quando ambos existem; caso contrário usa service.name. OTEL_SERVICE_NAME e OTEL_RESOURCE_ATTRIBUTES oferecem a mesma configuração. , embedding, pesquisa e orquestrador devem ter nomes diferentes e um comum.
Resumo rápido
Atributos de recurso descrevem o emissor e tornam a topologia do Mapa do Aplicativo confiável.
10. Crie spans, atributos, status e exceções
.get_tracer() obtém uma fonte de instrumentação. start_as_current_span() inicia, torna atual e encerra o span ao sair do bloco with. Use atributos com , como embedding.model, embedding.token_count, search.top_k, search.result_count, llm.prompt_tokens e llm.response_tokens. Evite prompts sensíveis, dados pessoais e nomes genéricos.
from opentelemetry import trace
from opentelemetry.trace import SpanKind, Status, StatusCode
tracer = trace.get_tracer("rag-pipeline")
with tracer.start_as_current_span("SearchVectorIndex") as span:
span.set_attribute("search.index_name", "support-docs")
span.set_attribute("search.top_k", 5)
try:
results = search_index(embedding, top_k=5)
span.set_attribute("search.result_count", len(results))
except Exception as error:
span.record_exception(error)
span.set_status(Status(StatusCode.ERROR, "Vector search failed"))
raise
with tracer.start_as_current_span("CallLlmApi", kind=SpanKind.CLIENT) as span:
span.set_attribute("gen_ai.request.model", model_name)
response = call_model(prompt)
Uma exceção não tratada que sai do contexto é registrada e marca erro automaticamente. Se o código a capturar, record_exception() e set_status() mantêm a evidência. SERVER e CONSUMER representam entrada; e PRODUCER, saída; INTERNAL representa trabalho local e é o padrão.
Resumo rápido
Spans nomeiam o trabalho, atributos dão contexto pesquisável, kind classifica a direção e status preserva a falha.
11. Modele uma requisição RAG com spans aninhados
Iniciar um span enquanto outro está atual cria automaticamente a relação pai-filho por meio das variáveis de contexto do Python. Não é necessário passar o pai para trabalho síncrono aninhado.
with tracer.start_as_current_span("ProcessQuery", kind=SpanKind.SERVER):
with tracer.start_as_current_span("GenerateEmbedding") as embedding_span:
embedding_span.set_attribute("embedding.token_count", token_count)
embedding = create_embedding(query)
with tracer.start_as_current_span("SearchVectorIndex") as search_span:
documents = search(embedding, top_k=5)
search_span.set_attribute("search.result_count", len(documents))
with tracer.start_as_current_span("CallLlm", kind=SpanKind.CLIENT) as llm_span:
llm_span.set_attribute("llm.prompt_tokens", prompt_tokens)
answer = generate_answer(query, documents)
llm_span.set_attribute("llm.response_tokens", answer_tokens)
A cascata resultante apresenta ProcessQuery como raiz e embedding, pesquisa e LLM como filhos. Oito segundos em CallLlm dentro de dez segundos totais expõem o gargalo. Em chamadas , clientes instrumentados injetam traceparent e servidores instrumentados o extraem.
Resumo rápido
Contextos aninhados expressam causalidade local; a propagação leva o mesmo a outros processos.
12. Exporte diretamente ou por um Collector
Na exportação direta, a instrumentação alimenta o , o exportador do serializa lotes e o processo envia ao ponto de . É a opção mais simples e o padrão da Distro. Um OpenTelemetry Collector acrescenta uma camada para transformações centralizadas, múltiplos e políticas comuns, mas se torna outro serviço operacional.
Exportação direta reduz infraestrutura; use Collector quando o processamento central ou vários destinos justificarem o custo operacional.
Resumo rápido
Prefira exportação direta e adote Collector apenas para uma necessidade concreta de processamento ou roteamento.
13. Controle volume e custo com amostragem
Amostragem percentual mantém uma fração representativa; amostragem limitada por taxa restringe novos por segundo. A Distro Python atual usa um amostrador limitado por taxa quando nenhuma estratégia é definida. OTEL_TRACES_SAMPLER e OTEL_TRACES_SAMPLER_ARG permitem alterar a política sem recompilar.
# Fixed percentage: about 10% of traces.
configure_azure_monitor(sampling_ratio=0.10)
# Or rate limited: at most about 1.5 traces per second.
configure_azure_monitor(traces_per_second=1.5)
# Equivalent environment configuration:
export OTEL_TRACES_SAMPLER="microsoft.fixed_percentage"
export OTEL_TRACES_SAMPLER_ARG="0.10"
Amostragem afeta , não métricas. podem acompanhar decisões de . Taxas baixas reduzem precisão, portanto prefira métricas não amostradas para alertas. Uma linha amostrada pode trazer itemCount, que representa vários eventos; use sum(itemCount), não a contagem bruta de linhas.
Resumo rápido
Controle custo sem ocultar falhas raras e não interprete linhas amostradas como o tráfego total.
14. Tolere falhas de exportação e verifique a
O exportador usa armazenamento offline local para transmissões malsucedidas e repete após falhas temporárias. O caminho de produção deve ser gravável, privado, monitorado e persistente o suficiente. disable_offline_storage remove essa proteção e só faz sentido quando a política proíbe persistência ou outra camada garante entrega.
configure_azure_monitor(
storage_directory="/var/telemetry/support-rag",
# Keep False in production unless local persistence is prohibited.
disable_offline_storage=False,
)
Gere tráfego de sucesso e falha.
Verifique a visão geral após o atraso normal de .
Abra Métricas ao Vivo para solicitações, dependências e exceções quase em tempo real; o recurso vem habilitado.
Consulte solicitações recentes e os nomes de função de nuvem.
Abra um e confirme operation_Id, pais e atributos.
Teste uma interrupção curta em ambiente controlado e acompanhe o armazenamento de repetição.
Resumo rápido
A verificação prova chegada, identidade, correlação, atributos e recuperação — não apenas que a aplicação continua executando.
15. Use Mapa do Aplicativo e diagnóstico de transações
O Mapa do Aplicativo reconstrói a topologia com nomes de função de nuvem e dependências correlacionadas. Nós são componentes e arestas são chamadas. Duração, volume e falhas ajudam a restringir a investigação.
Os detalhes da transação de ponta a ponta exibem uma linha do tempo semelhante a Gantt: raiz no topo, filhos recuados, trabalho sequencial em seguida e trabalho paralelo sobreposto. Selecione um evento para ver duração, código, propriedades e exceção. Acesse por Desempenho, Falhas, Pesquisa de transação ou pelo mapa.
Resumo rápido
O mapa encontra o serviço suspeito; os detalhes da transação explicam uma requisição correlacionada no tempo.
16. Analise distribuídos com KQL
KQL responde perguntas sobre muitas transações. contém entradas, dependencies contém trabalho e interno, contém e exceptions contém falhas. operation_Id conecta as tabelas no esquema clássico.
// Slow server operations by service.
requests
| where timestamp > ago(1h) and duration > 3s
| summarize slowRequests=count(), averageDuration=avg(duration)
by cloud_RoleName
| order by averageDuration desc
// Dependencies belonging to slow requests.
requests
| where timestamp > ago(1h) and duration > 5s
| project operation_Id, requestName=name, requestDuration=duration
| join kind=inner (
dependencies
| project operation_Id, dependencyName=name,
dependencyDuration=duration, dependencyTarget=target,
dependencyResult=resultCode
) on operation_Id
| order by requestDuration desc
// Embedding latency segmented by custom span attributes.
dependencies
| where name == "GenerateEmbedding"
| extend model=tostring(customDimensions["embedding.model"]),
tokenCount=toint(customDimensions["embedding.token_count"])
| summarize averageDuration=avg(duration), p95=percentile(duration, 95),
averageTokens=avg(tokenCount) by model
Dimensões personalizadas tornam a análise consciente da IA: segmente embedding por modelo e , pesquisa por quantidade de resultados e limiar e LLM por modelo e uso de . Não grave prompts, textos privados recuperados ou credenciais apenas para facilitar consultas.
Resumo rápido
Junte por operation_Id, agregue durações e use dimensões seguras para testar uma hipótese específica.
17. Diagnostique padrões de IA e conclua o laboratório
Padrões de diagnóstico
Sinal
Investigação
de embedding
Dependência longa ou com erro; compare embedding.model.
Cold start da pesquisa vetorial
Primeiros spans após inatividade lentos e depois normais; compare result_count.
Limitação de taxa do LLM
Dependências com 429 ou atrasos de repetição; correlacione de prompt e resposta.
Estouro da janela de contexto
Falha quando do prompt se aproximam do limite; não armazene o texto do prompt.
Crie alertas de latência e falha, Pastas de Trabalho para a integridade do e métricas personalizadas para tendências. O laboratório usa uma aplicação Flask em Python 3.12+, assinatura do , e a CLI do mais recente. Ele cria , instrumenta etapas de documentos e diagnostica um atraso simulado.
Crie o recurso e configure a cadeia no ambiente.
Instale a Distro e defina atributos estáveis.
Adicione spans pai e filho com seguros.
Gere tráfego normal, lento e com falha.
Localize o atraso no mapa e nos detalhes da transação.
Confirme a conclusão com KQL e salve uma visualização útil.
Remova o recurso e a cadeia local ao terminar.
export APPLICATIONINSIGHTS_CONNECTION_STRING="<application-insights-connection-string>"
az login
python -m flask --app app run
# Generate normal, slow, and failing requests, then inspect:
# Application Map -> Performance/Failures -> End-to-end transaction details -> Logs.
Resumo rápido
O laboratório termina quando topologia, um e uma consulta agregada sustentam o mesmo diagnóstico.
18. Avaliação comentada, checklist e referências
Decisões da avaliação
Pergunta
Melhor resposta
Motivo
Como propagar contexto ?
TraceContext no cabeçalho traceparent.
Transporta ID, span pai, versão e .
Onde configurar a cadeia em produção?
APPLICATIONINSIGHTS_CONNECTION_STRING.
Mantém configuração de implantação fora do código.
Exceção não tratada sai de start_as_current_span()
O registra a exceção e marca erro.
O gerenciador captura a falha antes de encerrar.
Onde aparece um span ?
dependencies / AppDependencies.
Ele representa uma chamada de saída.
Qual campo correlaciona o ?
operation_Id / OperationId.
Corresponde ao ID do OpenTelemetry.
Checklist final
Defina service.name estável e comum.
Verifique traceparent em cada fronteira.
Combine automação com poucos spans semânticos.
Use atributos com , baixa cardinalidade e sem dados sensíveis.
Classifique SpanKind corretamente.
Documente amostragem, armazenamento e retenção.
Valide mapa, transações, Métricas ao Vivo, KQL, alertas e Pastas de Trabalho.
Monitore lacunas, erros de exportação, armazenamento de repetição, custo e p95.
Uma solução pronta para produção une instrumentação semântica, correlação , exportação controlada, amostragem consciente de custo, entrega resiliente, diagnóstico visual, KQL e monitoramento proativo.