feat(workspace): log workspace and agent state changes - #1075
Open
aqandrew wants to merge 11 commits into
Open
Conversation
aqandrew
force-pushed
the
aqandrew/devex-661-connection-state-logs
branch
from
August 12, 2026 22:00
a1a27aa to
163a89b
Compare
aqandrew
force-pushed
the
aqandrew/devex-661-connection-state-logs
branch
from
August 13, 2026 00:40
163a89b to
082b4bb
Compare
EhabY
reviewed
Aug 13, 2026
aqandrew
force-pushed
the
aqandrew/devex-661-connection-state-logs
branch
from
August 13, 2026 18:46
082b4bb to
163a89b
Compare
aqandrew
force-pushed
the
aqandrew/devex-661-connection-state-logs
branch
from
August 13, 2026 20:26
163a89b to
d29fcbd
Compare
aqandrew
force-pushed
the
aqandrew/devex-661-connection-state-logs
branch
2 times, most recently
from
August 13, 2026 23:51
7f7439a to
370185b
Compare
aqandrew
force-pushed
the
aqandrew/devex-661-connection-state-logs
branch
from
August 13, 2026 23:54
370185b to
b69ba41
Compare
aqandrew
force-pushed
the
aqandrew/devex-661-connection-state-logs
branch
from
August 14, 2026 00:02
b69ba41 to
4e8b8c8
Compare
aqandrew
force-pushed
the
aqandrew/devex-661-connection-state-logs
branch
5 times, most recently
from
August 14, 2026 00:59
3c2be68 to
1fc0b0b
Compare
Collaborator
|
Should we include an entry in the changelog for the past 2 PRs + this? We only mention user-visible changes and these are worthy of it since it means sharing the logs or browsing them would give them an easy way to correlate logs to sessions. (also more logs so they can easily debug more) |
aqandrew
force-pushed
the
aqandrew/devex-661-connection-state-logs
branch
from
August 17, 2026 20:21
1fc0b0b to
0991842
Compare
Base automatically changed from
aqandrew/devex-661-session-id-requests
to
main
August 17, 2026 20:49
aqandrew
force-pushed
the
aqandrew/devex-661-connection-state-logs
branch
from
August 17, 2026 20:49
0991842 to
b1a22a8
Compare
aqandrew
force-pushed
the
aqandrew/devex-661-connection-state-logs
branch
2 times, most recently
from
August 18, 2026 16:26
c7dce24 to
6cabf20
Compare
EhabY
reviewed
Aug 18, 2026
EhabY
left a comment
Collaborator
There was a problem hiding this comment.
Nice cleanup, the split into two loggers resolves my second comment. My first one about duplication is only half done, and fixing it properly is the one structural change I'm after, left inline on workspaceMonitor.ts:145.
Shape I have in mind, three layers with one job each:
- detect: the observers, pure, no logger or telemetry imports, report a transition object
- record:
recordWorkspaceState/recordAgentStateinsrc/instrumentation/, telemetry only - log: inline in the monitor, same as every other logging call site here
Sorry this got a bit out of hand, I saw an opportunity for some refactoring and unifying :)
EhabY
reviewed
Aug 19, 2026
EhabY
reviewed
Aug 19, 2026
EhabY
reviewed
Aug 19, 2026
EhabY
reviewed
Aug 19, 2026
EhabY
reviewed
Aug 19, 2026
Add WorkspaceStateLogger, which logs workspace, agent, and lifecycle status transitions at info level with the old and new values. Wire it into WorkspaceMonitor so state changes observed while tracking a workspace are recorded (tagged with the session ID) for connection debugging.
…gers Address review feedback on the combined WorkspaceStateLogger: it logged once per agent for a single workspace-status change and duplicated the transition-detection already in the telemetry observers. - Add a shared TransitionTracker and use it in WorkspaceStateTelemetry and WorkspaceAgentTelemetry (no behavior change). - Split the logger into WorkspaceStateLogger (one log per workspace status change) and WorkspaceAgentLogger (per-agent status/lifecycle), mirroring the two telemetry observers. Both are wired in WorkspaceMonitor.
Mirror WorkspaceStateTelemetry: key the workspace state logger on status, transition, and reason, and include transition and reason in the log payload so a state-change line matches the telemetry event.
…lemetry Reshape workspace/agent state handling into three layers, one job each: - detect: WorkspaceStateObserver / WorkspaceAgentObserver report a transition object; stateful but effect-free (no logger/telemetry imports) - record: recordWorkspaceState / recordAgentState emit telemetry - log: inline in WorkspaceMonitor.update, matching the repo's other log sites Deletes the parallel WorkspaceStateLogger / WorkspaceAgentLogger classes and the WorkspaceStateTelemetry / WorkspaceAgentTelemetry classes. Agent state is now observed once in WorkspaceMonitor for every agent over the whole session, so WorkspaceStateMachine no longer tracks agent telemetry. Logs use flat scalar payloads and say "state observed" on first sight, "state changed" after, and log when an agent disappears.
The event now covers every agent for the whole monitored session (deduped), not just the connected agent during connection setup, and transitions are sampled from the workspace event stream so intermediate hops may coalesce.
Per CONVENTIONS.md, src/instrumentation is telemetry-only. The pure detection code has no telemetry or logger imports, so move TransitionTracker, WorkspaceStateObserver, WorkspaceAgentObserver, and the transition types to src/workspace/observers.ts. The record* functions stay in instrumentation and import the transition types from there. Observer/tracker tests move to test/unit/workspace/observers.test.ts.
aqandrew
force-pushed
the
aqandrew/devex-661-connection-state-logs
branch
from
August 19, 2026 23:46
0c10123 to
8400c8b
Compare
Drop the generic TransitionTracker. It was only used by the two observers, and the shared wrapper forced the awkward "nothing changed" / "first observation" double-check. Each observer now keeps its own previous-state memory and compares inline, shaping its result directly.
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.
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 (RFC req 7). It builds on #1074.
Changes
State handling is split into three layers, one job each:
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.recordWorkspaceState/recordAgentStateemit theworkspace.state_transitioned/workspace.agent.state_transitionedtelemetry events.WorkspaceMonitor.update(), with flat scalar payloads matching the repo's other log sites. Logsstate observedon first sight,state changedafterward, andagent <name> removedwhen an agent disappears.WorkspaceMonitoris now the single agent-observation site, soWorkspaceStateMachineno longer tracks agent telemetry.Important
Telemetry data change.
workspace.agent.state_transitionednow 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 insrc/telemetry/, so this lands as-is.EVENTS.mdis updated; heads-up to whoever owns the funnel queries.Testing
pnpm typecheck, targetedpnpm lint, fullpnpm test(2456 passing).record*event shapes, and the monitor's inline logging (observed vs changed, agent transitions across all agents, agent removal).Refactor design (reviewer's three-layer shape)
Per the review, the goal was to remove the duplication between the telemetry observers and the state loggers by making transition detection happen once:
recordWorkspaceState/recordAgentStateinsrc/instrumentation/, telemetry only.This deletes both
src/workspace/*Logger.tsfiles and leaves one tracker per concern.Observer API decision: observers return a transition object (workspace →
WorkspaceStateTransition | undefined; agents →{ transitions, removed }) andWorkspaceMonitor.update()logs inline and callsrecord*. This was chosen over a constructor callback becauseobserve()has a single synchronous caller, so a callback would only hide the side effects and complicate tests.🤖 Generated by Coder Agents.