Skip to content

feat: attach client_session_id to requests and set the CLI session env var - #1074

Merged
aqandrew merged 10 commits into
aqandrew/devex-661-session-loggerfrom
aqandrew/devex-661-session-id-requests
Aug 17, 2026
Merged

feat: attach client_session_id to requests and set the CLI session env var#1074
aqandrew merged 10 commits into
aqandrew/devex-661-session-loggerfrom
aqandrew/devex-661-session-id-requests

Conversation

@aqandrew

@aqandrew aqandrew commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

What

Propagate the session ID from Phase 1 to outbound API requests and to the CLI, so server-side logs, telemetry, and the spawned coder ssh process can all be correlated with the extension's session.

This is Phase 2 of 3 for DEVEX-661. It builds on #1073.

Changes

  • Requests (RFC req 3): add a sessionId argument to CoderApi.create and attach the session ID to every request via the W3C baggage header using the client_session_id key (baggage: client_session_id=<hex>), on both the REST default headers and the WebSocket handshake headers. Threaded through all CoderApi.create call sites, including the pre-auth OAuth/login/deployment clients, so every request carries it.
  • Telemetry (RFC req 4.2): already satisfied — the shared ID is the telemetry sessionId, which ships on every event's context.
  • CLI (RFC reqs 5.2/5.3): extend applySshEnvironment to also set CODER_TRACE_SESSION_ID on both process.env and the terminal environment collection, so the spawned coder ssh ProxyCommand reuses the plugin's session ID instead of generating its own.

Testing

  • pnpm typecheck, targeted pnpm lint, full pnpm test:extension (2108 passing).
  • New tests: baggage: client_session_id=<hex> present/absent on CoderApi; CODER_TRACE_SESSION_ID applied to process.env and the terminal collection and restored on dispose.

🤖 Generated by Coder Agents.

@linear-code

linear-code Bot commented Aug 11, 2026

Copy link
Copy Markdown

DEVEX-661

@aqandrew aqandrew changed the title feat: propagate the session ID to requests and the CLI feat: propagate the session ID to requests and CLI invocations Aug 11, 2026
@aqandrew
aqandrew force-pushed the aqandrew/devex-661-session-id-requests branch from f2f6512 to e6e52cc Compare August 12, 2026 22:00
@aqandrew
aqandrew requested review from EhabY and code-asher August 12, 2026 22:31
@aqandrew
aqandrew force-pushed the aqandrew/devex-661-session-id-requests branch from 0baf84a to 8d98780 Compare August 13, 2026 00:40
@aqandrew aqandrew changed the title feat: propagate the session ID to requests and CLI invocations feat: attach client_session_id to requests and set the CLI session env var Aug 13, 2026
Comment thread src/api/coderApi.ts Outdated
Comment thread src/api/coderApi.ts Outdated
Comment thread src/api/coderApi.ts Outdated
Comment thread src/core/container.ts Outdated
Comment thread src/remote/environment.ts Outdated
@aqandrew
aqandrew force-pushed the aqandrew/devex-661-session-id-requests branch 6 times, most recently from 0cc3e42 to 5d327f2 Compare August 14, 2026 00:03
aqandrew added a commit that referenced this pull request Aug 14, 2026
Add core/sessionId.ts exporting a single session ID constant (generated
once per activation) and remove newSessionId() from telemetry/ids.ts.
Consumers now import the constant directly instead of threading it through
constructors and CoderApi.create, so every CoderApi client attaches the
client_session_id baggage header unconditionally. Addresses review feedback
on #1074.
@aqandrew
aqandrew requested a review from EhabY August 14, 2026 01:00
Comment thread src/api/coderApi.ts Outdated
Comment thread src/core/sessionId.ts Outdated
Add SessionLogger, which wraps the Coder output channel and prefixes
every message with the activation's session ID so all log lines for a
session can be correlated by a single ID. Generate the ID once in the
ServiceContainer, reuse it as the telemetry session ID, and expose it
via getSessionId() for downstream consumers.
Attach the session ID to every API request via the W3C baggage header
(session_id=<id>) so the server can correlate requests with the
session's logs and telemetry, threading it through CoderApi.create at
all call sites.

Set CODER_TRACE_SESSION_ID on both process.env and the terminal
environment collection so the spawned `coder ssh` ProxyCommand reuses
the plugin's session ID instead of generating its own.
Align with the updated RFC: the session ID baggage key changes from
session_id to client_session_id.
Add core/sessionId.ts exporting a single session ID constant (generated
once per activation) and remove newSessionId() from telemetry/ids.ts.
Consumers now import the constant directly instead of threading it through
constructors and CoderApi.create, so every CoderApi client attaches the
client_session_id baggage header unconditionally. Addresses review feedback
on #1074.
@aqandrew
aqandrew force-pushed the aqandrew/devex-661-session-id-requests branch from fec1170 to 2c72a37 Compare August 17, 2026 20:21
@aqandrew
aqandrew merged commit b42cbbf into main Aug 17, 2026
11 checks passed
@aqandrew
aqandrew deleted the aqandrew/devex-661-session-id-requests branch August 17, 2026 20:49
aqandrew added a commit that referenced this pull request Aug 21, 2026
## What

Add info-level logging of workspace, agent, and lifecycle status
transitions so connection debugging has a record of state changes —
correlated by the session ID from #1073.

This is **Phase 3 of 3** for
[DEVEX-661](https://linear.app/codercom/issue/DEVEX-661) (RFC req 7). It
builds on #1074.

## Changes

State handling is split into three layers, one job each:

- **detect** — `WorkspaceStateObserver` / `WorkspaceAgentObserver`
(`src/instrumentation/workspace.ts`) each detect a transition once and
report a transition object. Stateful but effect-free (no
logger/telemetry imports). The agent observer tracks every agent by ID
and reports agents that disappear.
- **record** — `recordWorkspaceState` / `recordAgentState` emit the
`workspace.state_transitioned` / `workspace.agent.state_transitioned`
telemetry events.
- **log** — inline in `WorkspaceMonitor.update()`, with flat scalar
payloads matching the repo's other log sites. Logs `state observed` on
first sight, `state changed` afterward, and `agent <name> removed` when
an agent disappears.

`WorkspaceMonitor` is now the single agent-observation site, so
`WorkspaceStateMachine` no longer tracks agent telemetry.

> [!IMPORTANT]
> **Telemetry data change.** `workspace.agent.state_transitioned` now
covers **every agent for the whole monitored session** (deduped per
agent), rather than only the connected agent during connection setup. In
practice most workspaces have one agent, so volume is unchanged;
multi-agent workspaces and flaky connections emit more. There is no
sampling in `src/telemetry/`, so this lands as-is. `EVENTS.md` is
updated; heads-up to whoever owns the funnel queries.

## Testing

- `pnpm typecheck`, targeted `pnpm lint`, full `pnpm test` (2456
passing).
- Unit tests cover observer detection (first observation, dedup,
per-agent independence, removal, reset), the `record*` event shapes, and
the monitor's inline logging (observed vs changed, agent transitions
across all agents, agent removal).

<details>
<summary>Refactor design (reviewer's three-layer shape)</summary>

Per the review, the goal was to remove the duplication between the
telemetry observers and the state loggers by making transition detection
happen once:

- **detect**: pure-detection observers report a transition object; no
logger or telemetry imports.
- **record**: `recordWorkspaceState` / `recordAgentState` in
`src/instrumentation/`, telemetry only.
- **log**: inline in the monitor, same as every other logging call site.

This deletes both `src/workspace/*Logger.ts` files and leaves one
tracker per concern.

**Observer API decision:** observers return a transition object
(workspace → `WorkspaceStateTransition | undefined`; agents → `{
transitions, removed }`) and `WorkspaceMonitor.update()` logs inline and
calls `record*`. This was chosen over a constructor callback because
`observe()` has a single synchronous caller, so a callback would only
hide the side effects and complicate tests.

</details>

---

🤖 Generated by Coder Agents.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants