
Steven MasleyandCoder Agents
1afc6d4fd0
feat: structured disconnect attribution for agent logs (#25191)
Implements
[PLAT-60](https://linear.app/codercom/issue/PLAT-60/enhance-disconnect-logs-with-structured-reason-attribution):
adds structured disconnect attribution to disconnect logs throughout the
agent and tailnet packages.
Every disconnect log site now carries structured slog fields. All
existing logs remain; existing messages are preserved with the fields
added alongside.
New fields on disconnect log lines:
- `connect_type` — which layer disconnected: `server_to_agent`,
`agent_to_client`, or `client_to_server`
- `disconnect_reason` — categorical reason: `graceful`, `network_error`,
`server_shutdown`, etc.
- `disconnect_expected` — whether the disconnect is normal operation
(`true`) or should be investigated (`false`)
- `disconnect_initiator` — who started it: `client`, `agent`, `server`,
or `network` (control-plane sites only)
- `disconnect_detail` — free-form supplemental info (where useful)
## What's covered
**Control plane (`server_to_agent`):** coordination RPC, DERP map
subscriber, agent runLoop, agent Close, `BasicCoordination.Close`,
`Controller.run`.
**Data plane (`agent_to_client`):** SSH sessions, reconnecting PTY,
JetBrains port-forwarding.
<details>
<summary>Control-plane sites</summary>
| Site | Reason | Initiator |
|---|---|---|
| `agent/agent.go` `runLoop` EOF | `network_error` | `network` |
| `agent/agent.go` `runCoordinator` deferred exit | `server_shutdown` /
`graceful` / `network_error` | `agent` / `server` / `network` |
| `agent/agent.go` `runDERPMapSubscriber` deferred exit | same (shared
`classifyCoordinatorRPCExit`) | same |
| `agent/agent.go` `Close` shutdown timeout | `server_shutdown` + detail
| `agent` |
| `agent/agent.go` `Close` clean coord disconnect | `server_shutdown` |
`agent` |
| `tailnet/controllers.go` `BasicCoordination.Close` | `graceful` or
`network_error` | `c.initiator` |
| `tailnet/controllers.go` `Controller.run` `net.ErrClosed` |
`network_error` | `network` |
</details>
<details>
<summary>Data-plane sites</summary>
| Site | Reason | Notes |
|---|---|---|
| `agent/agentssh/agentssh.go` SSH session closed | free-form
(`graceful`, `process exited with error status: N`, etc.) | Also sets
`closeCause("normal exit")` for clean exits so coderd's
`connection_log.DisconnectReason` is no longer empty |
| `agent/reconnectingpty/server.go` PTY closed | `server_shutdown`,
error string, or `graceful` | |
| `agent/agentssh/jetbrainstrack.go` channel closed | `normal close` or
error string | Previously passed empty reason |
</details>
<details>
<summary>Bug fix</summary>
The deferred `disconnected from coordination RPC` log no longer fires
when the initial `Coordinate()` RPC call fails before any connection is
established.
</details>
Refs PLAT-60.
---
_This PR was prepared by Coder Agents on behalf of @Emyrk._
**Manually QA'd a lot of common disconnects**
---------
Co-authored-by: Coder Agents <noreply@coder.com>
2026-05-19 09:47:03 -05:00
..
2026-05-11 08:41:17 -06:00
2026-05-08 16:45:14 -04:00
2026-03-16 12:36:26 -05:00
2026-05-18 22:32:05 +01:00
2026-03-02 16:02:01 +01:00
2026-05-18 15:17:20 -04:00
2026-05-11 12:43:52 -05:00
2026-05-14 11:45:21 -04:00
2026-02-06 09:52:17 -07:00
2026-03-13 00:22:55 +11:00
2026-05-13 14:14:07 +00:00
2026-04-03 15:47:26 -05:00
2026-01-08 15:24:11 +04:00
2026-05-18 22:32:05 +01:00
2026-02-19 09:02:19 +00:00
2026-05-13 14:20:02 -06:00
2026-01-29 13:50:15 +01:00
2026-05-07 08:38:20 -06:00
2026-01-08 15:24:11 +04:00
2026-01-08 15:24:11 +04:00
2026-04-28 13:06:45 -07:00
2026-05-14 13:54:59 +01:00
2026-05-11 08:41:17 -06:00
2026-03-05 20:29:49 +00:00
2026-03-19 21:51:26 +00:00
2026-04-22 12:34:17 +02:00
2026-01-08 15:24:11 +04:00
2026-04-28 08:56:36 +01:00
2026-04-27 23:26:17 +03:00
2025-10-15 17:37:37 +00:00
2026-03-18 09:30:22 -05:00
2026-04-02 23:51:02 +02:00
2026-05-11 14:27:40 -05:00
2026-01-30 13:30:06 +01:00
2026-05-18 08:33:29 -04:00
2025-10-23 15:38:49 -05:00
2026-05-05 12:56:06 +10:00
2026-05-18 22:32:05 +01:00
2026-02-19 09:02:19 +00:00
2026-05-13 11:06:42 -04:00
2026-05-07 17:10:50 +01:00
2026-05-11 09:07:30 -06:00
2026-04-29 16:38:26 -07:00
2026-05-11 08:41:17 -06:00
2026-01-08 15:24:11 +04:00
2026-03-18 09:30:22 -05:00
2026-05-06 09:27:24 -07:00
2026-03-25 22:15:27 +00:00
2026-04-26 14:49:10 -07:00
2026-05-05 02:54:03 +05:00
2026-04-15 19:53:10 +01:00
2026-05-18 08:33:29 -04:00
2026-03-13 20:37:41 -07:00
2026-05-19 17:01:23 +10:00
2026-03-12 18:07:52 +02:00
2025-11-17 13:24:12 +00:00
2026-03-23 09:52:34 +00:00
2026-05-05 02:54:03 +05:00
2025-09-26 11:56:34 +02:00
2026-04-01 09:54:59 -04:00
2026-05-05 02:54:03 +05:00
2026-05-05 02:54:03 +05:00
2026-04-21 11:11:56 +01:00
2026-01-08 15:24:11 +04:00
2026-05-18 15:17:20 -04:00
2025-10-27 17:14:16 -06:00
2026-05-05 02:54:03 +05:00
2026-05-12 22:13:55 +10:00
2026-05-11 08:41:17 -06:00
2026-05-18 22:32:05 +01:00
2026-05-05 02:54:03 +05:00
2026-03-13 14:09:39 +00:00
2026-05-05 02:54:03 +05:00
2026-05-05 02:54:03 +05:00
2026-05-05 02:54:03 +05:00
2026-04-21 11:36:20 +10:00
2026-05-18 22:32:05 +01:00
2026-05-18 22:32:05 +01:00
2026-05-05 02:54:03 +05:00
2026-05-11 16:23:07 +10:00
2026-01-12 18:19:19 -08:00
2026-05-05 02:54:03 +05:00
2026-03-23 19:54:43 +00:00
2026-05-05 02:54:03 +05:00
2025-12-15 11:26:41 -06:00
2026-05-05 02:54:03 +05:00
2026-05-05 02:54:03 +05:00
2026-03-23 19:54:43 +00:00
2026-05-05 02:54:03 +05:00
2026-03-04 18:01:56 -08:00
2026-05-05 02:54:03 +05:00
2026-04-22 12:34:17 +02:00
2026-05-03 11:31:48 -04:00
2026-05-12 08:54:53 -04:00
2026-05-12 08:54:53 -04:00
2026-04-07 12:25:32 -06:00
2026-05-05 02:54:03 +05:00
2026-02-13 08:19:07 -06:00
2026-05-05 02:54:03 +05:00
2026-03-25 09:53:06 +00:00
2026-01-15 12:41:28 +03:00
2026-03-23 21:03:34 +00:00
2026-03-25 09:53:06 +00:00
2026-03-06 09:14:11 +00:00
2026-05-05 02:54:03 +05:00
2026-05-05 02:54:03 +05:00
2026-05-06 09:27:24 -07:00
2026-05-13 14:20:02 -06:00
2026-05-06 09:27:24 -07:00
2026-02-19 09:02:19 +00:00
2026-05-05 02:54:03 +05:00
2026-05-05 02:54:03 +05:00
2026-04-10 09:50:11 -05:00
2026-05-05 02:54:03 +05:00
2026-05-05 02:54:03 +05:00
2025-09-26 11:43:32 +02:00
2026-05-05 02:54:03 +05:00
2026-05-05 02:54:03 +05:00
2026-05-11 08:41:17 -06:00
2026-05-19 09:47:03 -05:00
2026-05-11 12:43:52 -05:00
2026-05-11 12:43:52 -05:00
2026-05-11 12:43:52 -05:00
2026-05-11 12:43:52 -05:00
2026-04-23 06:20:35 +10:00
2026-05-05 02:54:03 +05:00
2026-05-05 02:54:03 +05:00
2026-03-25 09:53:06 +00:00
2026-05-05 02:54:03 +05:00
2026-05-14 14:25:07 +01:00
2026-05-14 14:25:07 +01:00
2026-04-29 12:57:47 -06:00
2026-04-13 07:24:34 -06:00
2026-05-06 09:27:24 -07:00
2026-04-15 11:31:43 +02:00
2026-04-26 14:49:10 -07:00
2026-05-05 02:54:03 +05:00
2026-01-12 18:19:19 -08:00
2026-05-05 02:54:03 +05:00
2026-05-18 22:32:05 +01:00
2026-05-01 13:29:33 +01:00
2026-05-01 13:29:33 +01:00
2026-04-20 21:33:35 +10:00
2026-05-11 12:43:52 -05:00
2026-05-05 02:54:03 +05:00
2026-05-11 14:27:40 -05:00
2026-03-12 18:07:52 +02:00
2026-05-11 14:27:40 -05:00
2026-05-05 02:54:03 +05:00
2026-02-03 09:45:23 +00:00
2026-05-05 02:54:03 +05:00
2026-05-05 02:54:03 +05:00
2026-05-18 08:33:29 -04:00
2026-05-13 14:14:07 +00:00
2026-05-11 11:03:38 +02:00
2026-05-11 12:43:52 -05:00
2026-05-13 14:20:02 -06:00
2026-01-08 15:24:11 +04:00