feat: opt-in telemetry + crash reporting (#616) - #621
Conversation
…616) - ~/.codeframe/telemetry.json (enabled/prompted/anonymous_id), atomic writes - Resolution: CODEFRAME_TELEMETRY env > DO_NOT_TRACK > file > default OFF - Command + crash event builders; crash frames limited to in-package paths, exception messages omitted (privacy) - send_events never raises; fire-and-forget daemon-thread variant
…crash capture (#616) - main() console-script entry wraps app(): one-time opt-in prompt (interactive TTY only, default No), command timing, exit-code capture, unhandled-exception crash event; exceptions/exit codes propagate unchanged - Command names resolved against the registered Typer tree — raw argv tokens can never leak into telemetry - Suite-wide CODEFRAME_TELEMETRY=off setdefault in root conftest
- scripts/telemetry_collector.py: self-hostable FastAPI endpoint appending events to JSONL (cheapest backend for beta volume), 100-event batch cap - PRIVACY.md: exactly what is/isn't collected, consent precedence, endpoint, 90-day retention, deletion path; linked from README
…dex review) All three entry points (console scripts, python -m codeframe, python -m codeframe.cli) now share the same main() wrapper.
|
Warning Review limit reached
More reviews will be available in 2 hours, 14 minutes, and 31 seconds. Learn how PR review limits work. Your organization has run out of usage credits. Purchase more credits in the billing tab to continue. ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (18)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
Code Review — feat: opt-in telemetry + crash reporting (#616)This is a well-architected, privacy-first implementation. The design decisions are sound: default-off, sanitized crash frames, no args/paths leaking, fire-and-forget transport, and complete test isolation via conftest. A few things worth addressing before merge. Correctness / Minor Bugs1. Double config read in Two independent 2. Collector has no concurrent write protection (scripts/telemetry_collector.py) with LOG_PATH.open("a") as f:
for event in batch.events:
f.write(json.dumps({...}) + "\n")Under async uvicorn, two simultaneous requests will both enter this block. Each Test Coverage Gap3.
assert event["frames"] == [] # exception raised outside package; all frames filteredDesign Observations (non-blocking)4. This is a semi-internal Typer API. The choice is correct — it's the only way to get the registered command tree for safe argv filtering — but a comment explaining why a private API is used deliberately would help future readers. 5. Two concurrent first-run invocations can both see no config file and both write, with the second write's 6. Unprovisioned endpoint (acknowledged) PRIVACY.md correctly documents that What's done well
SummaryIssues #2 (collector concurrency) and #3 (vacuous test) are worth a quick fix. #1 is trivial cleanup. None are blockers for a beta rollout, but #2 could produce a silently corrupted log file under concurrent load — recommend addressing before the collector goes live. |
…ingle-write, explicit empty-frames assertion (#621)
Follow-up Review — All Prior Issues ResolvedAll three items from my first review have been addressed in the current diff: #1 — #2 — Collector concurrent write interleaving fixed. #3 — Vacuous test giving false coverage signal fixed. The two non-blocking design observations remain outstanding but do not warrant a re-request:
No blocking issues remain. The implementation is solid: privacy-by-design, correct exit-code propagation, hermetic test suite, and the collector concurrency fix lands before the endpoint goes live. Ready to merge. |
Third-pass Review — No New FindingsScanned the full diff again. The three corrected issues from review #1 remain fixed, and no new issues have been introduced since review #2. The two outstanding non-blocking observations are still present:
Nothing has changed to block merging. Previous verdict stands: ready to merge. |
Final Triage Summary (PR #621)Cutoff: 2026-06-12T19:45:16Z (last push, docs sync commit 68637c4) Fixed
Skipped (with justification)
Hard gates
|
Summary
Implements #616: Launch: opt-in telemetry + crash reporting.
codeframe/core/telemetry.py(headless): consent state at~/.codeframe/telemetry.json(enabled/prompted/anonymous_id), resolution chainCODEFRAME_TELEMETRYenv →DO_NOT_TRACK→ config file → default off; command/crash event builders; fire-and-forget httpx sender that never raises.cf config telemetry on|off|status— newcf configTyper group;statusshows effective state and which override produced it.codeframe/cli/telemetry_runtime.py+main()inapp.py): one-time opt-in prompt (interactive TTY only, default No), command timing, exit-code capture, unhandled-exception crash capture. All three entry points (cf/codeframeconsole scripts,python -m codeframe,python -m codeframe.cli) route through it. Exit codes and exceptions propagate unchanged.scripts/telemetry_collector.py— self-hostable ~50-line FastAPI JSONL appender (cheapest thing that works for beta volume).CODEFRAME_TELEMETRY=offso tests never prompt or send.Acceptance Criteria
cf config telemetry on|off; honored everywhere including non-interactive runs (env var)Test Plan
pytest tests/ --ignore=tests/e2e -m v2exit 0) + ruff + mypy (191 files) cleanpython -m codeframebypassed wrapper) fixed in a0ea9daKnown Limitations / Intentionally Deferred
raise typer.Exit(1)(the common CodeFRAME pattern) produce a failed command event but no crash event — crash reports are for unhandled exceptions only, per the issue contract.telemetry.codeframe.devdefault endpoint is not yet provisioned — until it is deployed, opted-in sends fail silently (by design); self-hosters useCODEFRAME_TELEMETRY_ENDPOINT.uv syncfor the console-script change (:app→:main) to take effect.Implementation Notes
DO_NOT_TRACKis honored as an extra off-switch (console DNT convention) — explicitCODEFRAME_TELEMETRY=onstill wins as the more specific signal.Closes #616