feat: add chat lifecycle stage tracing, metrics, and Grafana dashboard - #28741
Draft
jscottmiller wants to merge 1 commit into
Draft
feat: add chat lifecycle stage tracing, metrics, and Grafana dashboard#28741jscottmiller wants to merge 1 commit into
jscottmiller wants to merge 1 commit into
Conversation
Instrument chatd with OpenTelemetry spans and a Prometheus histogram
covering the full chat turn lifecycle: queue wait, capacity wait,
acquisition, preparation, MCP connect, provider attempts, streaming,
time to first token, thinking, tool calls, commit, and compaction.
Spans and coderd_chatd_stage_duration_seconds{stage,scope,model,effort}
observations are emitted from one shared StageTracer path so traces and
metrics cannot drift. Turn-scoped work is separated from detached
background quickgen calls via the scope label, and the resolved model
and effective reasoning effort are recorded as both span attributes and
histogram labels.
Add a Grafana dashboard (examples/monitoring/dashboards/grafana/
chatd-lifecycle) with an aggregate stage flamegraph driven by a
selectable statistic (mean, p50, p90, p95, p99), stage trends, time
share, scheduling waits, TTFT, throughput, and background provider
call panels, filterable by model and effort.
Contributor
Docs previewCheck off each page once it's been reviewed. If a page changes in a later push, its checkbox clears automatically so it gets a fresh look. Pages not yet wired into the docs navigation aren't listed here. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Instruments chatd with OpenTelemetry spans and a Prometheus histogram covering the full lifecycle of an Agents chat turn, and adds a Grafana dashboard that renders the aggregate stage profile as a flamegraph with selectable summary statistics (mean, p50, p90, p95, p99) plus summary panels for the whole pipeline.
What's included
chatloop.StageTracer: a shared helper that emits each lifecycle stage as both an OTel span and an observation on a newcoderd_chatd_stage_duration_seconds{stage, scope, model, effort}histogram from a single code path, so traces and metrics cannot drift. Stages:chat_turn,queue_wait,capacity_wait,acquisition,generation_step,prepare,mcp_connect,provider_attempt,time_to_first_token,stream,thinking,tool_call,commit,compaction.scope="background"so it cannot skew turn-level aggregates.resolveModelCall, the same value sent to the provider) are recorded as span attributes and histogram labels, threaded through toprovider_attemptvia the transport.examples/monitoring/dashboards/grafana/chatd-lifecycle/(dashboard JSON + README with per-panel explanations): stage flamegraph and hierarchy bar chart, stage duration trends, time share ofchat_turn, scheduling waits p99, TTFT, turn/stage rates, and background provider calls, filterable by$model/$effortwith a$statstatistic selector. All queries are NaN-safe so rare stages render as 0 rather than breaking the flamegraph's nested-set ordering.--trace+ standard OTel env vars); per-session drill-down renders eachchat_turnas a root span tree in any tracing UI (verified with Tempo).Verification
Verified end to end against a live dev deployment with Tempo + Prometheus + Grafana: 100+ real chat turns across two models, exact count agreement between trace spans and histogram observations for every stage, clean span nesting (no children outliving parents, no negative offsets), HTTP >= 400 provider attempts marked as span errors, and the dashboard rendering in Grafana 11.4 (including a headless render check of the flamegraph panel).
Not sampled in the test environment (code paths exist, environment never triggers them):
capacity_wait(the premium license disables the concurrent-agent cap via unlimitedagent_runtime_hours),mcp_connect(no MCP servers configured),compaction(context never neared the threshold).Notes and known limitations
chat_turnspans are standalone trace roots: the turn executes asynchronously on a worker (possibly another replica) and no trace context is persisted, so linking to the originating HTTP request span is not possible without persisting a traceparent.chat_turnis runner-scoped (same boundary as the debug turn): a queued follow-up folds into the preceding turn span rather than starting a new one.chat_turn,queue_wait,capacity_wait,acquisition) carry emptymodel/effortlabels; filtering the dashboard by model narrows the view to the generation stages. Noted in panel descriptions.temperaturemay only be set to 1 when thinking is enabled") from Anthropic models and succeeds on retry; now cleanly visible asscope="background"error spans. Worth a separate issue.Implementation plan
Chat lifecycle observability: flamegraph + summary dashboard
Goal
A Grafana dashboard showing where time goes across all Agents chat sessions: an aggregate flamegraph of lifecycle stages with a selectable summary stat (mean, median, p90/p95/p99), plus per-stage summary panels. Per-session drill-down comes for free via Tempo traces.
Current state (from code survey)
coderd_chatd_ttft_seconds.messagepartbufferrecords model-invocation and per-tool start/end (used only on interrupt);generation_preparer.gologs prep duration;chatdebug.RecordingTransportmeasures each provider HTTP round trip, but only into the opt-inchat_debug_*tables.CommitSteppersistence, compaction.coderd/tracing/exporter.go), Prometheus is already served; no new export plumbing needed, config only.Stage model
stream,thinking, andtool_calloverlapprovider_attempt/each other in wall time; the flamegraph is a stage-time profile, not a strict non-overlapping decomposition.Work items
trace.Tracerinto the chat worker;chat_turnroot span per turn; child spans per the stage model; span attributes for provider, model, chat kind, top-level vs subagent, generation attempt, tool name, error status.coderd_chatd_stage_duration_seconds{stage}recorded at the same points the spans end (shared helper so spans and metrics cannot drift); log-spaced buckets 10ms..10m.$statvariable (mean/p50/p90/p95/p99); per-stage trends; stage time-share; TTFT; retries; queue wait.Resolved decisions
examples/monitoring/dashboards/(repo conventiongrafana/<name>/dashboard.json).chat_turnspans are standalone roots (span link to the inbound request was planned but dropped: no trace context is persisted across the async worker boundary).Additions during implementation (from live verification)
scopelabel/attribute separating turn work from detached background quickgen calls.modelandeffortlabels/attributes for dashboard filtering.queue_wait,acquisition), parented underchat_turn.organizerename sets display name, not field name; the panel requires real field nameslabel/value/self/level).🤖 This PR was generated by Coder Agents on behalf of @jscottmiller.