Observability
Um usuário recebeu “não foi possível concluir”, mas você não consegue repetir a falha. A observabilidade deve permitir reconstruir a execução com os registros produzidos no momento: qual requisição entrou, quais etapas aconteceram, onde uma dependência falhou e quanto tempo e uso cada tentativa consumiu. Esse é o objetivo desta aula, além de simplesmente ter um painel bonito.
Usaremos traces, spans e logs para representar um assistente com recuperação, geração e ferramenta. Você aprenderá a distinguir caminhos observáveis de decisão de raciocínio privado, atribuir custo sem inventar tarifas e escolher entre OpenTelemetry, LangSmith, Phoenix e MLflow conforme integração e governança. A entrega será uma captura em que uma falha pode ser investigada sem reproduzir manualmente o pedido original.
JavaScriptIA & MLAvaliaçãoAo terminar esta aula
- Observe caminhos executados, versões e resultados.
- Mensure ponta a ponta e por tentativa.
- Telemetria deve ser útil sem capturar segredos desnecessários.
Antes de continuar: Laboratório: Evals II
Traces e spans: uma árvore com relógio e contexto
FundamentosUm trace representa o percurso de uma operação distribuída, enquanto um span descreve uma etapa com início, fim e atributos. Uma requisição pode ter um span raiz e filhos para retrieval, chamada de modelo e consulta de compra. O identificador do trace correlaciona o conjunto; parentSpanId mostra a relação entre etapas. Propague esse contexto quando atravessar HTTP, filas e workers, ou o trabalho em segundo plano parecerá uma execução sem origem. Um span não precisa guardar todo o conteúdo da conversa para explicar sua duração e seu status.
Considere duas etapas paralelas que duram 300 e 400 milissegundos. Somá-las e dizer que a requisição demorou 700 ignora a sobreposição: a duração ponta a ponta depende do caminho crítico. Em um fluxo sequencial, por outro lado, durações somadas podem aproximar o total, descontadas lacunas e overhead. Registre tempos monotônicos para medir duração dentro do processo e timestamps para correlacionar eventos. Relógios entre máquinas podem divergir; não tire conclusões causais apenas pela ordenação visual dos horários.
Logs correlacionados e minimização de dados
FundamentosLogs registram eventos discretos: validação recusada, retry agendado, ferramenta sem resposta. Um log estruturado contém campos pesquisáveis, como traceId, spanId, eventName e errorType, em vez de uma frase livre difícil de agrupar. Ao relacioná-lo ao span, você consegue saber em qual etapa o evento ocorreu. Separe uma categoria controlada de erro da mensagem bruta da dependência, que pode conter informação sensível. A pergunta operacional é “qual classe de falha ocorreu e onde?”, não “como armazenar tudo que passou pelo sistema?”.
Não grave tokens de acesso, cookies ou cabeçalhos completos. A remoção de um campo chamado password não cobre segredos presentes em texto livre. Defina uma política de captura para prompts, respostas e documentos, com redaction, acesso e retenção proporcionais ao risco. Para depuração comum, IDs de documento, versões e tamanhos podem ser suficientes. Quando amostrar conteúdo, indique que o trace é incompleto. Ausência de um log em um pipeline amostrado não demonstra que o evento nunca aconteceu.
Tokens e custo: ledger de tentativas, não contador de respostas
IA & MLCada chamada ao modelo pode reportar uso de entrada, saída e categorias adicionais conforme o provedor. Preserve o uso reportado e o identificador do modelo; não presuma que texto dividido por quatro reproduz a tokenização. Em um agente com retries, todas as tentativas podem consumir recursos, incluindo as que não produzem uma resposta útil. Some uso por tentativa e depois agregue por requisição e tenant. Mantenha separado o uso real, a estimativa prévia e o valor faturado conciliado.
O custo calculado depende da tabela de preços, moeda, data e categoria de token. Valores promocionais, caching e contratos podem mudar o resultado. Guarde a versão da tarifa usada no cálculo, em vez de atualizar retrospectivamente todo o histórico sem aviso. As convenções semânticas de GenAI ajudam a padronizar campos, mas seu estado e nomes precisam ser conferidos na versão adotada. O exemplo local desta aula usa unidades fictícias e não afirma uma cobrança real de qualquer provedor.
Latência, falha de ferramenta e decision paths
FundamentosPara atribuir latência, capture fila, retrieval, modelo, ferramentas e serialização. Uma resposta lenta pode ter modelo rápido e fila longa. Registre tentativas separadas: uma consulta que falhou em 800 milissegundos e um retry que venceu em 100 contribuíram juntos para a espera. Para falhas, marque status e categoria coerentes com a semântica do span; uma dependência pode falhar enquanto a requisição completa por fallback. Essa diferença deve aparecer no trace e no resultado final.
Decision paths são decisões observáveis da aplicação: rota escolhida, documento selecionado, validação recusada e aprovação solicitada. Não equivalem ao pensamento privado do modelo. Um atributo routeReason:"budget" explica uma política programada; uma justificativa textual gerada pode não explicar causalmente a execução. Prefira registrar entradas e regras realmente usadas pelo roteador. Para reconstruir uma falha, preserve versão de prompt, política, ferramenta e esquema, além de IDs. Sem versão, o mesmo nome de componente pode representar comportamentos diferentes ao longo do tempo.
OpenTelemetry e opções de plataforma
FundamentosOpenTelemetry oferece um padrão para instrumentação e exportação de sinais, permitindo escolher um backend compatível. LangSmith, Phoenix e MLflow fornecem experiências de tracing e avaliação com integrações específicas. A escolha depende do stack, da necessidade de avaliação integrada, dos dados que podem sair do ambiente e da operação que a equipe consegue manter. Nenhuma interface substitui a definição de spans e atributos úteis. Antes de escolher, instrumente o mesmo fluxo mínimo e verifique se os eventos críticos aparecem com correlação.
↗ Traces↗ LangSmith Observability↗ Setup Tracing↗ MLflow Tracing for LLM and Agent Observability
Compare também controle de acesso, retenção, exportação e comportamento sob perda do coletor. Se o backend de telemetria ficar indisponível, a aplicação precisa de uma política explícita: buffer limitado, descarte contabilizado ou bloqueio em situações de auditoria obrigatória. Não deixe uma fila de logs crescer sem limite. Um dashboard mostra o que foi capturado; ele não garante completude, segurança ou correção da tarefa. A revisão do trace deve ser acompanhada da avaliação funcional definida nas semanas anteriores.
↗ Traces↗ LangSmith Observability↗ Setup Tracing↗ MLflow Tracing for LLM and Agent Observability
Reconstruir uma falha a partir de JSON local
JSONSalve trace.cjs e execute node trace.cjs. Este pequeno formato didático não é um SDK OpenTelemetry; ele torna visível a correlação que você deve preservar ao adotar um SDK. Os tempos e o uso foram escritos como fixtures para que o teste seja determinístico.
const assert = require('node:assert/strict');
const spans = [
{traceId:'t1',id:'root',parent:null,name:'request',start:0,end:180,status:'ok'},
{traceId:'t1',id:'s1',parent:'root',name:'retrieve',start:0,end:30,status:'ok'},
{traceId:'t1',id:'s2',parent:'root',name:'lookup',start:30,end:130,status:'error',errorType:'timeout'},
{traceId:'t1',id:'s3',parent:'root',name:'fallback',start:130,end:180,status:'ok',inputTokens:40,outputTokens:10}
];
const logs=[{traceId:'t1',spanId:'s2',eventName:'tool.timeout'}];
const failed=spans.find(s=>s.status==='error');
assert.equal(failed.name,'lookup');
assert.ok(logs.some(l=>l.spanId===failed.id));
assert.equal(spans[0].end-spans[0].start,180);
console.log({failed,finalStatus:spans[0].status,
tokens:spans.reduce((n,s)=>n+(s.inputTokens||0)+(s.outputTokens||0),0)});A ferramenta falha, mas o span raiz termina com status ok porque o fluxo tomou um fallback válido. Essa distinção permite alertar sobre a dependência sem afirmar que toda tarefa falhou. O total de 50 tokens é somente a soma das fixtures; não há preço associado. Se o fallback não atender ao contrato do produto, a avaliação funcional deve marcar a tarefa como incompleta mesmo com transporte bem-sucedido.
Exercício aplicado
O dashboard mostra status ok na requisição, mas um usuário relata que a compra não foi consultada. Use o trace para distinguir sucesso de transporte, fallback e conclusão funcional.
- Localize a raiz e os filhos pelo traceId.
- Identifique erro de lookup e log correlacionado.
- Verifique qual decisão de fallback foi registrada.
- Compare a resposta final com o contrato da tarefa.
Abrir resolução comentada
O span raiz pode estar ok quando a aplicação entregou uma resposta válida por fallback. O trace prova que a consulta falhou e que outro caminho foi executado; não prova que o objetivo original foi concluído. A classificação funcional depende da política de encaminhamento.
Para investigar sem reproduzir, preserve os IDs, versões e categorias de erro. Não é necessário armazenar credenciais ou raciocínio privado. Se o conteúdo necessário não foi capturado, a análise deve assumir evidência insuficiente em vez de inventar a causa.
const assert = require('node:assert/strict');
const spans = [
{traceId:'t1',id:'root',parent:null,name:'request',start:0,end:180,status:'ok'},
{traceId:'t1',id:'s1',parent:'root',name:'retrieve',start:0,end:30,status:'ok'},
{traceId:'t1',id:'s2',parent:'root',name:'lookup',start:30,end:130,status:'error',errorType:'timeout'},
{traceId:'t1',id:'s3',parent:'root',name:'fallback',start:130,end:180,status:'ok',inputTokens:40,outputTokens:10}
];
const logs=[{traceId:'t1',spanId:'s2',eventName:'tool.timeout'}];
const failed=spans.find(s=>s.status==='error');
assert.equal(failed.name,'lookup');
assert.ok(logs.some(l=>l.spanId===failed.id));
assert.equal(spans[0].end-spans[0].start,180);
console.log({failed,finalStatus:spans[0].status,
tokens:spans.reduce((n,s)=>n+(s.inputTokens||0)+(s.outputTokens||0),0)});Como conferir seu resultado
- Logs e spans preservam traceId e vínculo correto.
- Timeout e fallback aparecem como etapas diferentes.
- Uso inclui todas as tentativas capturadas.
- Nenhum segredo de teste permanece no export local.
Aplique em um problema novo
Primeiro resolva sem consultar a resposta. Explique suas decisões e guarde a evidência. A conclusão de leitura é independente desta autoavaliação.
Confira seus pré-requisitos
- Ler árvore parent/spanId e tempos.
- Correlacionar logs sem dados desnecessários.
Root 300 ms ok; lookup 20–220 erro; fallback 220–300 ok. Usuário precisava lookup confirmado. Reconstrua sucesso.
Conferir raciocínio e critérios de domínio
Rootok mostra resposta entregue; não confirma a consulta solicitada. A decisão é conclusão funcional incompleta porque lookup falhou e fallback não forneceu a confirmação.
lookup durou 200 ms e fallback 80 ms; root durou 300 ms. Somar spans sobrepostos não mede latência total; a árvore mostra a dependência.
O diagnóstico usa traceId/spanId e errorType, sem token ou payload privado. A ausência de confirmação deve continuar visível ao usuário.
Evidências para autoavaliação ou revisão por pares
- Causalidade: Rootok mostra resposta entregue; não confirma a consulta solicitada. A decisão é conclusão funcional incompleta porque lookup falhou e fallback não forneceu a confirmação.
- Métricas: lookup durou 200 ms e fallback 80 ms; root durou 300 ms. Somar spans sobrepostos não mede latência total; a árvore mostra a dependência.
- Privacidade: O diagnóstico usa traceId/spanId e errorType, sem token ou payload privado. A ausência de confirmação deve continuar visível ao usuário.
Um erro frequente
Status ok significa tarefa concluída.
Status de transporte e sucesso da tarefa são contratos distintos.
Teste sua compreensão
Responda com suas palavras antes de abrir o comentário. Saber explicar uma decisão é parte do domínio.
1. O trace revela o raciocínio privado do modelo?
2. Por que a soma de spans paralelos pode exceder a duração total?
Porque os intervalos podem se sobrepor.
A latência ponta a ponta depende do caminho crítico.
3. Um backend sem eventos prova ausência de falhas?
Não.
Amostragem, perda e exportação indisponível podem gerar lacunas.
Seu progresso fica salvo neste navegador. Concluir a leitura não substitui demonstrar o domínio nos exercícios.
Referências e aprofundamento
Documentação oficial e trabalhos originais. As referências registram o escopo e as limitações para você conferir o que sustentam.
- Traces
OpenTelemetry • consulta: 2026-10-06
FundamentosTrace, span, contexto, relações pai-filho, eventos e status de execução.
Limites: Instrumentação mostra operações registradas; não revela raciocínio privado do modelo.
- Logs
OpenTelemetry • consulta: 2026-10-06
FundamentosLogs estruturados e correlação com contexto de traces.
Limites: Coleta e retenção dependem da implementação; evitar registrar segredos e conteúdo sensível desnecessário.
- MLflow Tracing for LLM and Agent Observability
MLflow • consulta: 2026-10-06
AgentesIA & MLAvaliaçãoEntradas, saídas, metadados, latência e uso de tokens por etapa; integração OpenTelemetry.
Limites: Custo financeiro exige cálculo adicional com tarifas vigentes; traces só cobrem etapas instrumentadas.
- Spend Tracking
LiteLLM • consulta: 2026-10-06
FundamentosRegistro de uso e gasto, atribuição a chaves/usuários e consulta de custos.
Limites: Estimativa de custo depende das tarifas e dos metadados de uso; reconciliar com faturamento do provedor.
- OpenTelemetry GenAI Semantic Conventions
OpenTelemetry • consulta: 2026-10-06
FundamentosRepositório oficial atual de convenções para spans, métricas e eventos GenAI, MCP e provedores.
Limites: A documentação anterior no site informa migração para este repositório; verificar versão e suporte da instrumentação.
- LangSmith Observability
LangChain • consulta: 2026-10-06
AvaliaçãoTracing de aplicações LLM e agentes, depuração e observação de etapas.
Limites: Opção de implementação, não obrigação curricular; configuração e acesso aos dados requerem atenção.
- Setup Tracing
Arize Phoenix • consulta: 2026-10-06
FundamentosSetup de tracing e instrumentação de aplicações LLM.
Limites: Escolher uma ferramenta para o laboratório; a página não prova equivalência funcional entre produtos.