agent-proxy: instrument the request path with OTel spans + structlog events (tracer/logger are declared but never called) #28
Labels
No labels
burndown-2026-08
autonomy
async-consult
autonomy
epic
autonomy
headless
autonomy
live-collab
coherence-core
priority
P0
priority
P1
priority
P2
priority
P3
priority
P4
qa-fixture
role/advocate
role/director
role/exec
role/frontend
role/gamedev
role/human
role/platform
role/qa
role/science
role/sysadmin
state
ambient
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
coilyco-flight-deck/agent-proxy#28
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Want
Make agent-proxy actually emit the per-request detail its obs layer only declares today.
app/obs.pywiresget_tracer()(OTLP HTTP exporter, off unlessPROXY_OTEL_EXPORTER_OTLP_ENDPOINTis set) andget_logger()(structlog JSON), but there are zerostart_as_current_spanand zerologger.*call sites on the request path - so a SigNoz sees no traces anddocker logsshows nothing per-request. Prometheus/metricsis already fully wired (24 points); this ticket adds the trace + structured-log channels so localhost high-detail inspection works.Ask
Instrument the request path end to end:
main.py(/v1/chat/completions,/v1/completions), with child spans wrapping the real stages: queue enqueue/wait (queue.py), each upstream attempt (upstream.py), response validation (resilience.py), and each retry / fallback / circuit transition (resilience.py). The causal chain (which backend, which attempt, why it fell back) is the whole point.gen_ai.*(request model,gen_ai.usage.input_tokens/output_tokens,response.finish_reasons) plusagentproxy.*(logical model, resolved backend, dialect, trust tier if present) per the design notes in agent-proxy#18. SetOTEL_SEMCONV_STABILITY_OPT_IN=gen_ai_latest_experimental.loggerevent per backend attempt and per terminal outcome (ok / rejected / failed / truncation-avoided / validation-failure), carrying the same dims. These are the localhostdocker logs/Dozzle high-detail stream.Detail vs redaction
Full span/log detail (prompt/completion/tool payloads) is for a local OTLP backend only - the shared fleet SigNoz (
ser8:4318) has no ingest redaction. So: put bodies behind an explicit high-detail flag (e.g.PROXY_TRACE_BODIES=1, default OFF) so the default export is metadata-only and safe for any sink, and full bodies are an opt-in you enable when pointing at localhost. Document the flag.Coordination
upstream.py,analysis.py, andresilience.pyare being actively rewritten by in-flight runs: agent-proxy#3 (dialect adapter in upstream.py), #4 (intent-detection in analysis.py), #19 (reliability harness). Expect to integratemainand rebase onto their changes before landing - instrument the post-rebase shape, do not fight them.Acceptance
PROXY_OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318, a request produces a trace whose span tree shows queue -> upstream attempt(s) -> validation -> outcome, with gen_ai.* token/finish attributes.docker logs agent-proxyshows a structured event per backend attempt and terminal outcome.Refs
🔒 Reserved by
ward agent --driver codex— containerengineer-codex-agent-proxy-28on hostkais-macbook-pro-2.localis carrying this issue (reserved 2026-07-02T09:31:24Z). Concurrentward agentruns are blocked until it finishes or the reservation goes stale (2h0m0s TTL);--forceoverrides.— Codex, via
ward agentWARD-OUTCOME: done - added request-path spans and structured logs
The work stayed mostly mechanical once the request flow was mapped. The only friction was keeping the async span boundaries and the no-op path aligned without breaking the existing tests. Confidence is good, but the stream path still deserves a little real-world smoke testing with OTLP enabled.