Skip to content

Tracing distribuído — Tempo + OpenTelemetry

Read in your language: English · Português · Español

Status do escopo (pós-congelamento de escopo 2026-05-10) — Ver ARCHITECTURE.md para os 37 MÓDULOs canônicos + 7 Test Kinds + arquitetura de safety DOM/CPOS/PIE-PA. ADRs 0014, 0019-0025 cobrem adições pós-Freeze.

Status: receiver OTLP do Tempo habilitado (gRPC :4317 + HTTP :4318). Os agentes browser-engine + synthetic-load têm o código do OpenTelemetry SDK embarcado (agent/src/telemetry.ts), opt-in via scripts/tracing-toggle.sh. Instrumentação das personas Caddy é follow-up pendente (requer rebuild via xcaddy com o módulo caddy-otel).

Por que tracing distribuído aqui

A medição central deste test bed é a latência por requisição experimentada quando um agente (browser engine ou synthetic-load engine) fala com um webserver de persona através do NGFW sob teste. Uma única requisição cruza quatro hops:

browser-engine/synthetic-load agent  →  NGFW (DUT, TLS leg 1)  →  NGFW (TLS leg 2)  →  Caddy persona
     hop 1                      hop 2                 hop 3                 hop 4

Sem tracing distribuído, o operador só enxerga a latência black-box end-to-end da perspectiva do agente. Uma regressão de 50 ms pode estar no NGFW, na persona Caddy ou no kernel Linux entre eles — métricas do Prometheus sozinhas não dizem qual.

Tracing distribuído expõe o breakdown por hop, que é exatamente o que appliances comerciais (Spirent CyberFlood, Ixia BreakingPoint) não expõem. Esse é um diferenciador estratégico deste projeto — e o motivo pelo qual embarcamos o código do SDK no nível do agente mesmo mantendo-o OPT-IN por padrão.

Opt-in por padrão — considerações de footprint de performance

Tracing distribuído está desabilitado por padrão. Os agentes rodam com seu footprint normal de memória + CPU até que o operador o habilite explicitamente.

Por que opt-in: a frota de agentes é projetada para altas contagens de agentes (browser engine 1–300, synthetic-load engine 1–1000) em hardware de laboratório que pode ter restrições de memória/CPU. Não queremos que todo operador pague o custo do SDK em toda execução de teste; queremos que ele escolha pagá-lo durante medições de baseline e execuções de deep-dive.

Footprint quando HABILITADO (medido em Ubuntu 22.04 + Node 20):

Recurso Por agente browser engine Por agente synthetic-load engine
Memória RSS +10–15 MB +5–10 MB
CPU em estado estável <1% <1%
Latência por requisição adicionada ~50–100 µs ~50–100 µs
Overhead de latência por requisição vs baseline de 200 ms ~0,05% ~0,05%

Mitigações já embutidas no overlay: - Sampling probabilístico em 10% (OTEL_TRACES_SAMPLER_ARG=0.1). No pico da frota (300 browser engine × 1 ciclo/5 s) isso resulta em ~6 traces/s chegando ao Tempo - @opentelemetry/instrumentation-fs desabilitado — fs é ruidoso e irrelevante - Exporter HTTP (não gRPC) — keep-alive, sem dependências binárias extras - Fila do BatchSpanProcessor limitada (OTEL_BSP_MAX_QUEUE_SIZE=2048) para que a memória seja previsível - Kill-switch OTEL_SDK_DISABLED=true sempre respeitado

Como habilitar

Após subir o cluster em qualquer modo de deployment:

sudo ./scripts/k8s-install.sh --mode=<single|dual|tri|multi> ...

# Apply the tracing overlay on top of the running deployment.
./scripts/tracing-toggle.sh on

Os agentes pegam as novas env vars na próxima rotação de pod:

kubectl rollout restart deployment/web-agent deployment/k6-agent -n web-agents

Verifique se o SDK iniciou (procure pela linha [telemetry] OpenTelemetry SDK started):

kubectl logs -n web-agents deploy/web-agent | grep telemetry
kubectl logs -n web-agents deploy/k6-agent  | grep telemetry

Abra a UI do Tempo para ver os traces:

kubectl port-forward -n web-agents svc/tempo 3200:3200
# then visit http://localhost:3200

Como desabilitar

Duas opções:

# (a) Kill switch via env var — survives until next overlay re-apply
kubectl set env deployment/web-agent -n web-agents OTEL_SDK_DISABLED=true
kubectl set env deployment/k6-agent  -n web-agents OTEL_SDK_DISABLED=true
kubectl rollout restart deployment/web-agent deployment/k6-agent -n web-agents

# (b) Permanent — re-apply the base manifests (overlay stripped)
kubectl apply -k overlays/<your-mode>/
kubectl rollout restart deployment/web-agent deployment/k6-agent -n web-agents

Como o trace se parece

Quando habilitado, cada ciclo do browser engine se torna um span pai:

[span] web-agent: cycle (1.2s)
  ├─ [span] http: GET https://shop.persona.internal/  (340 ms)
  │   ├─ [span] dns: lookup shop.persona.internal  (2 ms)
  │   ├─ [span] tcp: connect 10.1.1.2:443  (8 ms)
  │   ├─ [span] tls: handshake  (45 ms)   ← agent → NGFW (TLS leg 1)
  │   └─ [span] http: response  (285 ms)  ← NGFW → persona (TLS leg 2 + content)
  ├─ [span] http: GET .../static/main.css  (120 ms)
  └─ ... per-resource child spans

Trace IDs propagam via headers W3C padrão traceparent / tracestate. O NGFW deve preservar esses headers — a maioria dos firewalls modernos preserva; alguns paths de inspeção QUIC resetam headers, então para traces HTTP/3 use fallback para HTTP/1.1 ou rode com TLS decrypt ON para que o NGFW reconstrua a requisição.

O que NÃO está sendo traçado (ainda)

  • Personas Caddy: o Caddy 2.7+ tem uma diretiva de tracing built-in mas o módulo caddy-otel precisa ser compilado na imagem via xcaddy. Agendado para um PR de follow-up. Até isso ser entregue, o trace termina na resposta HTTP do agente — você verá a requisição sair do agente e completar, mas não o breakdown do que a persona fez internamente
  • Spans do NGFW: vendors de NGFW tipicamente não emitem OTLP. O NGFW aparece implicitamente como tempo gasto entre o envio HTTP do agente e a resposta HTTP da persona. Para atribuir esse tempo com precisão, ou configure o mirror port do NGFW para um collector ciente de spans OU use as métricas de CPU + queue depth do SNMP exporter como proxy aproximado

Planejamento de armazenamento do Tempo

Com sampling de 10% e uma frota synthetic-load engine de 1000 agentes rodando 100 RPS cada: - Spans/s ingeridos: 100.000 × 0,1 ≈ 10.000 spans/s - Tamanho médio do span: ~500 B - Bytes/s: ~5 MB/s - Armazenamento para 24 h: ~430 GB

Defaults em observability/tempo/tempo.yml: - block_retention: 24h - max_block_bytes: 100 MiB - Backend de armazenamento: local (PVC)

Aumente block_retention para 7d para retenção mais longa; provisione o PVC adequadamente.

Roadmap

Fase Status O que cobre
Receiver OTLP do Tempo habilitado ✅ entregue (PR-4 #179) gRPC :4317 + HTTP :4318
Código do OpenTelemetry SDK no agente ✅ entregue (este PR) Wrappers para browser-engine + synthetic-load
Helper de toggle opt-in ✅ entregue (este PR) scripts/tracing-toggle.sh
Módulo OTel da persona Caddy ⏳ follow-up Rebuild da imagem via xcaddy + diretiva de tracing no Caddyfile
Correlação de spans do NGFW ⏳ pesquisa Específico de vendor; potencialmente via queue-depth do SNMP como proxy
Dashboards orientados por trace ⏳ follow-up Service map auto-construído a partir de spans, metrics_generator do Tempo já cabeado

Veja também