feat(desktop): anonymous launch ping, crash device info, /stats page#3985
Merged
Conversation
Crash reports alone answer "what broke" but not "for whom" or "how many are even running this". Three additions, all on the existing worker: - Launch ping: one POST per start with a random install id + version + OS facts. Gated on new desktop.telemetry config (default on, toggle in Settings > Updates, disclosed in desktop/README.md); dev builds never ping. Carries no conversation, key, or file data. - Crash reports now attach coarse device facts (OS version, CPU model, cores, RAM) so "only crashes on X" patterns are visible. - Worker grows /v1/ping (per-day install dedup with opens counter) and a Basic-auth /stats page (daily actives, version/platform breakdown, recent crash groups) so day-to-day reading needs no SQL.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Follow-up to #3978. Crash reports tell us what broke; this adds the "for whom / how many" half, still entirely on our Cloudflare account.
Anonymous launch ping
One POST per desktop start to
crash.reasonix.io/v1/ping: a random install id (16 bytes fromcrypto/rand, stored next to the global config, tied to nothing else), version,GOOS/GOARCH, and OS version string. That is the complete payload — no conversations, keys, paths, or hardware serials.Consent posture, since the client is open source and the community rightly cares:
desktop.telemetryconfig (default on), toggle in Settings → Updates → Anonymous usage ping, disclosed indesktop/README.md.version == "dev") never ping, so local hacking stays silent.Device facts on crash reports
ReportCrashnow attaches coarse machine info — OS version, CPU model, logical cores, RAM — so "only crashes on Windows 11 ARM" patterns become visible. Windows readsRtlGetVersion/registry/kernel32, macOS shells out tosysctl/sw_vers, Linux parses/proc+/etc/os-release; the parsers are portable and unit-tested./statspage on the workerBasic-auth (password in a worker secret), zero external assets, renders straight from D1: daily active installs + opens (30d), version and platform breakdown (7d distinct installs), recent crash groups. Day-to-day reading needs no SQL; per-day install dedup happens in SQL via
ON CONFLICT (date, install_id)with anopenscounter.Already deployed and verified live
D1 migrated (
devicecolumn,pingstable), worker deployed with the second rate-limit binding (30/min for pings vs 5/min for reports),STATS_PASSWORDsecret set. Verified on production: ping dedup (two pings → one row,opens = 2), device JSON stored,/stats200 with auth and 401 without/with wrong password. Smoke rows cleaned.Verification
internal/configtests pass (round-trip includes the newtelemetrykey); desktopgo vet+ new unit tests pass (install-id stability, ping POST round-trip, dev-build skip, devinfo parsers).tsc --noEmit: zero new errors vs baseline. Worker package typechecks clean.Notes
crash_app.goshows as a whole-file diff locally undergofmt -ldue to CRLF checkout; committed content is LF like the rest of the tree.