Skip to content

feat(telemetry): anonymous usage telemetry — documented schema, opt-out, public ingest worker#834

Merged
colbymchenry merged 1 commit into
mainfrom
feat/anonymous-telemetry
Jun 12, 2026
Merged

feat(telemetry): anonymous usage telemetry — documented schema, opt-out, public ingest worker#834
colbymchenry merged 1 commit into
mainfrom
feat/anonymous-telemetry

Conversation

@colbymchenry

Copy link
Copy Markdown
Owner

Summary

Adds anonymous usage telemetry to the engine: which commands and MCP tools get used, which languages get indexed, which agents connect — so language/agent support work goes where real usage is. Designed trust-first for a local-first tool:

  • The schema is the allowlist. Every collected field is documented in TELEMETRY.md; the ingest endpoint (telemetry-worker/, public in this repo on purpose) enforces that list and drops everything else. Never code, file paths, file/symbol names, queries, or IP addresses.
  • Consent done properly. The installer asks up front with a visible default-on toggle (asked once, never re-asked); headless paths print a one-line stderr notice before the first send — recording only buffers locally and stays silent, so the installer's toggle always precedes any notice. DO_NOT_TRACK=1 honored. Off is off: nothing recorded, no socket opened, buffered data deleted.
  • Telemetry may never cost the user anything. Zero new dependencies (global fetch), zero stdout (MCP protocol channel), zero hot-path latency (in-memory increment, counted after the tool reply is on the wire), fail-silent everywhere, bounded 256 KB local buffer, no retries. CLI commands ending in process.exit() are handled via a tiny synchronous exit-append; sends piggyback on long-running commands and the daemon's unref'd interval.
  • Volume scales with machines, not calls: usage aggregates locally into per-day rollups; only completed days send.

Surface

  • codegraph telemetry status|on|off (+ CODEGRAPH_TELEMETRY=0, DO_NOT_TRACK=1)
  • Events: install (targets/scope/kind), index (languages + coarse buckets), usage_rollup (per-day per-tool counts + MCP clientInfo attribution), uninstall
  • Docs: TELEMETRY.md (user contract), README section, docs/design/telemetry.md (engineering contract), CHANGELOG entry under Unreleased

Test plan

  • 20-unit telemetry suite: consent precedence, off ⇒ zero fetch/files, rollup aggregation, completed-day gating, re-queue on failure, hung-endpoint timeout, buffer cap + corrupt-line recovery, stale-claim merge-back, no-stdout invariant
  • Full suite: 1448 passing / 71 files (suite-wide CODEGRAPH_TELEMETRY=0 guard so spawned CLI/MCP test processes never pollute real telemetry)
  • Live e2e: real codegraph init → notice → POST → Worker → PostHog, verified; production endpoint live-verified (GET / info text, valid POST 204, garbage 400, rate limit 429 after 6/min)

🤖 Generated with Claude Code

…ut, public ingest worker

Adds anonymous usage statistics (commands/tools used, languages indexed,
connecting agents) with a strict, auditable allowlist. Never code, paths,
file/symbol names, queries, or IPs.

- src/telemetry/: zero-dep client — consent resolution (DO_NOT_TRACK >
  CODEGRAPH_TELEMETRY > stored choice > default-on), random machine UUID,
  in-memory counters → capped JSONL buffer → completed-day rollups; sync
  exit-append (survives process.exit) + opportunistic bounded sends; the
  first-run notice gates the first SEND, never local buffering, so the
  installer's consent toggle always precedes it. Off is off: no recording,
  no socket, buffered data deleted.
- codegraph telemetry status|on|off; per-command counting via preAction hook.
- MCP: tool counting after the reply is on the wire (session + proxy
  in-process fallback), agent attribution from initialize clientInfo,
  unref'd daemon flush interval. Zero hot-path cost, zero stdout.
- Installer: visible default-on consent toggle (asked once, never re-asked),
  install/index/uninstall lifecycle events.
- telemetry-worker/: public Cloudflare Worker behind telemetry.getcodegraph.com
  — allowlist validation, IP stripping, per-machine rate limit, forwards to
  PostHog as anonymous events. Ships nowhere with the npm package.
- TELEMETRY.md (field-by-field contract) + README section + design doc.
- 20 unit tests; suite-wide CODEGRAPH_TELEMETRY=0 guard so tests never
  pollute real telemetry. Full suite: 1448 passing.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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.

1 participant