Thanks to visit codestin.com
Credit goes to github.com

Skip to content

feat: add chatd lifecycle stage tracer - #28969

Draft
jscottmiller wants to merge 1 commit into
scott/chatd-stages/1-extract-stepfrom
scott/chatd-stages/2-stage-tracer
Draft

feat: add chatd lifecycle stage tracer#28969
jscottmiller wants to merge 1 commit into
scott/chatd-stages/1-extract-stepfrom
scott/chatd-stages/2-stage-tracer

Conversation

@jscottmiller

@jscottmiller jscottmiller commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Adds chatloop.StageTracer, which emits each chat lifecycle stage as both an OpenTelemetry span and an observation on a new coderd_chatd_stage_duration_seconds{stage, scope, chat_kind, model} histogram from a single call, so trace and metric durations cannot disagree. Nothing calls it yet; the following PRs instrument the chat loop, the provider transport, and the runner.

  • Stage and attribute name constants, StageModel, and context carriers for scope (turn / background) and chat kind (root / subagent). Scope and kind are plain context values so they survive a no-op tracer provider.
  • Start, StartRoot, StartRootAt for live spans; Record / RecordAs for stages reconstructed from timestamps. End is idempotent; EndWithoutObservation closes the span without a histogram sample.
  • A nil *StageTracer, nil provider, or nil metrics is usable and discards.
  • coderd_chatd_stage_anomalies_total{reason} counts stage observations dropped for a negative duration or an inverted window instead of dropping them silently.
  • Duration buckets are 16 round boundaries from 50ms to 1h (0.05 0.1 0.25 0.5 1 2.5 5 10 20 30 60 120 300 600 1800 3600) so alert thresholds land on bucket edges. Reasoning effort is a span attribute (reasoning_effort) but not a metric label: it multiplies series per model while changing only the model-call stages.
  • New server option --chat-stage-metrics / CODER_CHAT_STAGE_METRICS (off, basic, full; default off) selects how much is exposed as metrics. off registers none of the stage families; basic observes the wait, connect, and model-call stages (chat_turn, queue_wait, capacity_wait, acquisition, mcp_connect, stream, time_to_first_token, provider_attempt, tool_call, commit, retry_backoff); full observes every stage. Empty or unrecognized values resolve to off. Spans are emitted at every level. Families disabled by the level are still constructed against no registerer so every recorder is callable, and coderd_chatd_stage_metrics_level{level} reports the configured level.

Part of the chatd lifecycle observability stack: 1 extract step · 2 stage tracer · 3 stream stages · 4 provider attempts · 5 turn span · 6 capacity wait · 7 turn accounting · 8 dashboard. Supersedes the experimental branch in #28741.

🤖 This PR was generated by Coder Agents on behalf of @jscottmiller.

@github-actions

github-actions Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Docs preview

Check 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.

Add StageTracer, which starts one OpenTelemetry span and records one
coderd_chatd_stage_duration_seconds observation per chat lifecycle
stage from the same call, so span and histogram durations cannot
diverge. Stages carry a scope, chat kind, and model identity read from
the context or set on the span, and stages reconstructed from persisted
timestamps are emitted through Record and RecordAs. Windows with
inverted or negative durations are dropped and counted on
coderd_chatd_stage_anomalies_total by reason.

The histogram is labelled by stage, scope, chat kind, and model.
Reasoning effort is a span attribute only, since it multiplies series
per model without changing how the wait and connect stages behave.
Buckets are 16 round boundaries from 50ms to 1h so alert thresholds
land on bucket edges.

Add --chat-stage-metrics (CODER_CHAT_STAGE_METRICS), off|basic|full,
default basic. Basic observes the wait, connect, and model-call stages
only; full observes every stage; off registers none of the stage
families. Families disabled by the level are still constructed against
no registerer so every recorder is callable at every level. A
coderd_chatd_stage_metrics_level gauge reports the configured level.
@jscottmiller
jscottmiller force-pushed the scott/chatd-stages/2-stage-tracer branch from f5bfc09 to 0643175 Compare September 11, 2026 19:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

experimental Changes that might not necessarily be merged, until its approved to proceed with.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant