feat(gateway): unsupported-engine telemetry beacon + Grafana counter #177
Reference in New Issue
Block a user
Delete Branch "feature/unsupported-engine-telemetry"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What
The follow-up to the old-Android-WebView support (#176): tell the owner how many real clients hit the unsupported-engine screen, and on which engines, on the Grafana Scrabble — Users dashboard beside the existing App opens count.
index.htmlboot guard): on the hard gate (noBigInt/Proxy) or the reactive net (uncaught boot error), fire one fire-and-forget beaconPOST /telemetry/unsupported—navigator.sendBeaconwith afetchfallback, deduped inlocalStorageby app version + reason + Chromium, so a user reopening the app is one report, not ten.POST /telemetry/unsupportedhandler (the client never booted → no session), per-IP public-limited + body-capped (mirrors the export-download route). Folds the beacon into the OTel counterunsupported_engine_total{reason, chromium}with reason allow-listed and the Chromium major reduced to a bounded range (normalizeUnsupported) so a spoofed beacon cannot inflate metric cardinality; the full user agent is logged, not labelled./telemetry/*added to the@gatewaymatcher (else it falls to the landing catch-all — the lesson from/dict).Design (as agreed)
Dedup client-side; rate-limit + body-cap on the gateway (Caddy's stock build has no
rate_limitmodule, so the limiter is Go-side; the global body cap already covers it); the counter lands in Prometheus → Grafana for volume, the UA in the gateway logs / Tempo for detail.Verified
go build/vet/test ./gateway/...+gofmtclean. New tests: metric split,normalizeUnsupported(cardinality bounding), the handler route (204 / 405 / counter increment).check/build/e2e(188) green — the beacon is inert on a capable engine.addInitScript): exactly onePOST /telemetry/unsupported, deduped on reopen, labelsno_bigint/148/ version correct.Contour verification of the served
/telemetry/unsupportedroute to follow after the deploy.The index.html boot guard now fires a fire-and-forget beacon (POST /telemetry/unsupported) when it turns a client away on the unsupported-engine screen, so the owner can see — on the Users dashboard beside "app opens" — how many real clients hit it and on which engines. - Client: navigator.sendBeacon (fetch fallback) with a localStorage dedup keyed by app version + reason + Chromium, so a user reopening the app is one report, not ten. - Gateway: a new unauthenticated POST /telemetry/unsupported handler (the client never booted, so it carries no session), per-IP public-limited and body-capped, mirroring the export-download route. It folds the beacon into the OTel counter unsupported_engine_total {reason = no_bigint/no_proxy/boot_error/other, chromium}, with reason allow-listed and the Chromium major reduced to a bounded range (normalizeUnsupported) so a spoofed beacon cannot inflate the metric cardinality; the full user agent is logged, not labelled. - Caddy: /telemetry/* added to the @gateway matcher (else it falls to the landing catch-all). - Grafana: two panels on the Scrabble — Users dashboard (by reason, by Chromium major). - Docs: ARCHITECTURE.md §11. Tests: recordUnsupportedEngine (metric split), normalizeUnsupported (cardinality bounding), and the handler route end to end (204 / 405 / counter). go build+vet+test and gofmt clean; ui check/build/e2e green; the client beacon + dedup verified against a forced hard-gate (BigInt removed) — one POST, deduped on reopen, correct reason/chromium/version labels.