feat(desktop): surface why a terminal can't connect + emit failure telemetry

Merged
KI
4mo ago
+284-47

Why

When a terminal pane can't connect, it just shows "disconnected" with no cause — which is exactly what made the recent cross-region relay bug hard to spot (control plane worked, only the terminal WS 502'd). The root difficulty: the browser WebSocket API hides the upgrade's HTTP status — a relay 502/503 only surfaces as close code 1006, so the client can't see why.

What

Both changes lean on the _whoowns preflight the client already fires before every terminal WS (its response status was thrown away until now).

1. Classify the failure (surface the why). On give-up, the pane log now says the cause instead of a generic close:

  • preflight 503 → "This host is offline (not connected to the relay)."
  • preflight 401/403 → "You don't have access to this host."
  • preflight 200 but the WS still drops → "The host is online (region X) but the terminal stream couldn't connect — usually a relay routing issue." ← the fingerprint of the cross-region bug
  • preflight unreachable → "Couldn't reach the relay service."

2. Emit terminal_connect_failed telemetry on give-up (PostHog), so this failure mode is queryable/alertable instead of silent:
{ endpoint, close_code, close_reason, preflight_status, tunnel_region, reconnect_attempts, category } (endpoint has the token stripped).

Notes

  • primeRelayAffinity now returns { status, region } | null (was void); both existing callers ignore the value, so it's backward-compatible.
  • Fires once per give-up (max reconnect attempts reached), not on every transient blip.
  • Pure classifier + probe-parsing are unit-tested and mutation-checked. Desktop typecheck + biome clean.

Follow-on ideas from the same discussion (not in this PR): a bounded error state with Retry/Copy-diagnostics buttons, and a cross-region synthetic check in the relay (today's synthetic.ts only exercises same-region).


Open in Stage

Summary by cubic

Surface why a terminal can’t connect and emit telemetry on final failure. We classify errors using the relay _whoowns preflight (now probed with the wsUrl), show a clear message in the pane, and send a PostHog event for alerting.

  • New Features

    • Show a specific reason on give-up: 503 host offline, 401/403 no access, 200-but-WS-drops = relay routing issue (with region), 502/504 = temporary relay failure, or relay unreachable.
    • Emit terminal_connect_failed on give-up with endpoint, close_code, close_reason, preflight_status, tunnel_region, reconnect_attempts, category.
    • Only applies to relay-host terminals (/hosts/...); local terminals unchanged.
  • Refactors

    • @superset/workspace-client primeRelayAffinity now returns { status, region } | null (and exports RelayAffinityProbe) and is used to classify failures; added unit tests for probe parsing and classification.
    • Probe _whoowns with the original wsUrl (not actualUrl); deduplicated diagnostics comments and centralized rationale in primeRelayAffinity.

Summary by CodeRabbit

  • New Features
    • Terminal connections now run a relay-aware precheck for relay-routed hosts and generate more specific user-facing failure diagnoses.
  • Bug Fixes
    • Improved “max reconnect attempts reached” reporting with expanded diagnostic context (failure category, preflight status, tunnel region when available) and more detailed failure analytics.
  • Tests
    • Added/expanded automated coverage for relay affinity probing and terminal failure classification to ensure consistent categorization across common HTTP and stream-drop scenarios.