feat: add client_connected telemetry and surface/client labels for the IDE funnel
Issue for this PR
Closes #
Type of change
- New feature
What does this PR do?
Makes the IDE-extension onboarding funnel measurable from backend telemetry.
Context: ~92% of installs run the VS Code extension (telemetry source="datamates"), which runs altimate serve as its backend. On that process we emit startup_ready and then nothing until session_start (the first model prompt), so the large launch -> first-message drop was invisible.
Two additions:
- New
client_connectedevent. Emitted once per process the first time an authenticated client subscribes to the event stream (GET /eventor/global/event). It lives in a.usemiddleware after basic-auth inServer.createApp, so unauthenticated probes/health checks don't count. This splits the launch->session drop into "backend launched but no client connected" vs "connected but no message sent". Added toANCHOR_EVENTSso it flushes immediately. It fires for every surface (serve,run,tui); the IDE-funnel read filterssurface=="serve", and the other surfaces give a baseline to compare against. startup_readygainssurface.surfacemirrors the existingcommandfield, butclient_connectedhas nocommand, sosurfaceis the single key that joins the two funnel stages in queries.
Telemetry-only, fail-safe (dynamic import + .catch), non-blocking. The server.ts change is wrapped in altimate_change markers (upstream-shared file); the telemetry module is under src/altimate/** (altimate-owned, no markers required).
Not carrying a separate client field (review note): an earlier revision also added client = ALTIMATE_CLI_CLIENT to both events. The independent review pointed out toAppInsightsEnvelopes already stamps source = ALTIMATE_CLI_CLIENT onto every event that has no source of its own — so client was an exact duplicate of source (dashboards can already filter on source=datamates). It was dropped.
How did you verify your code works?
- Unit (telemetry):
bun teston the telemetry suites — 394 pass, 0 fail. Assertsstartup_readycarriessurface, andclient_connectedfires exactly once per process across repeated calls. - Server wiring (new,
test/server/altimate-client-connected-wiring.test.ts): drives real requests throughServer.createAppand asserts the middleware callsTelemetry.clientConnected()forGET /eventandGET /global/event, and not for other paths or non-GET methods. Verified non-vacuous by mutating the path literal (positive cases then fail). The one case not exercised — "move the hook above basic-auth so unauthenticated probes count" — is called out in the test file:Flag.OPENCODE_SERVER_PASSWORDis a module-level const frozen at load and CI runs the package in one process, so a runtime password toggle can't drive a 401; the ordering is enforced structurally by registering the hook immediately after the basic-auth.use. - Typecheck:
bun run typecheckon the opencode package — clean (exit 0).
Marker placement checked by hand against script/upstream/utils/config.ts (the --markers guard currently no-ops against the v2 upstream baseline).
Screenshots / recordings
N/A (backend telemetry only).
Checklist
- I have tested my changes locally
- I have not included unrelated changes in this PR
[!NOTE]
Low Risk
Telemetry-only changes with fail-safe dynamic import; server middleware adds a lightweight post-handler on event-stream routes without altering stream behavior.
Overview
Adds IDE onboarding funnel telemetry so launch → first-message drop can be split into “server up but no client” vs “client connected but no prompt.”
client_connected fires once per process when a real client opens the SSE bus on GET /event or GET /global/event. Server middleware runs after auth, only on 2xx, and dynamically calls Telemetry.clientConnected(). The event is an anchor (immediate flush). startup_ready now includes surface (same value as command) so dashboards can join funnel stages on one key.
The in-process trace consumer sets x-altimate-trace-consumer so its default /event subscription is not counted as an external client on serve startups.
Tests cover the telemetry latch, surface on startup_ready, and server middleware wiring (paths, GET-only, header skip, non-event routes).
Reviewed by Cursor Bugbot for commit 45fc7441fdd1bcd9ff18c00ceaee83b5c00a8ea7. Bugbot is set up for automated code reviews on this repo. Configure here.
Summary by CodeRabbit
- New Features
- Telemetry now records when a client connects, including the command surface and time since startup. Connection events are reported once per process when an event stream is requested.
- Startup-ready telemetry now includes the command surface, providing additional context for startup activity.