Repository navigation
feat(telemetry): report user-facing errors to the admin Errors page - #2674
Open
MusabShakeel576 wants to merge 3 commits into
Open
MusabShakeel576 wants to merge 3 commits into
MusabShakeel576 wants to merge 3 commits into
Conversation
Adds the app's half of the Errors page contract: `reportError()` builds a `ClientErrorEvent` (uuid, device time, platform, app version, current screen, Amplitude device id), strips credentials from the message and the text the user saw, cuts every field to the contract limits and queues it. The queue batches to POST /accounts/v1/errors/ingest every 2s or at 20 events (at most 50 per request, 200 held, oldest dropped), sends an identical kind+code+message+endpoint once per 5s, retries a failed batch once and then drops it, and flushes when the app goes to the background or the web page is hidden. It sends with the app's normal auth (Bearer + X-Platform on native, cookies on web) and resends a 401 once anonymously instead of refreshing, so an expired session cannot loop with the error being reported. Nothing is sent from dev builds, during web pre-rendering, or when EXPO_PUBLIC_ERRORS_INGEST_ENABLED=false. qa does not have lib/utils/userFacingError yet (master does, from the Pimlico key leak fix); it is copied verbatim from master, with its test, so the two merge cleanly. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017rhTzZBfBRybucitFXRFMW
…crashes
- Failed flows: track() mirrors every error event (`*_failed`, `*_error`,
`*_rejected`, `*_declined`, `*_blocked`, `*_unavailable`, plus
region_unavailable_shown and qr_scanner_permission_denied) with its
Title-Cased Amplitude name, a flow inferred from the name, and the
reason read from whichever key the call site used. It does so even
with `{ amplitude: false }`, which is about double-counting in
Amplitude. The store-review and Trustpilot "unavailable" events are not
app failures and stay out.
- Error toasts: `Toast.show` is wrapped once, so every `type: 'error'`
toast is reported with exactly the text it showed, without touching
the call sites. A cancelled prompt is reported as info.
- API failures: the global fetch is wrapped once. For our own services
only (accounts, rewards, analytics, vault manager; never the ingest
endpoint itself), a 4xx/5xx is reported with the backend's code and
message read from a clone, and a connection failure is reported as a
warning. The caller gets the same Response or the same error; other
hosts get the original promise. 401s (the token refresh retries them)
and 404s on reads (card status, Bridge customer, What's New and others
answer "none" that way on every app open) are not failures.
- Crashes: the error boundary sends one crash event carrying the id
Sentry.captureException returned, so the Errors page can link to
GlitchTip; its error_boundary track is not mirrored a second time.
The installers are wired up in the next commit.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017rhTzZBfBRybucitFXRFMW
…he user
The root layout installs the fetch and toast reporters before the app
renders and keeps the current screen for error reports.
GlitchTip now knows who hit an error: it follows the selected user in
the store, which every sign-in path (login, signup, restored session,
account switch) ends at and every sign-out clears, and sets
`{ id: userId, username }` — the backend user id, never the Turnkey
suborg id or the email; sendDefaultPii stays off. Captures that still
pass `user: { id: suborgId }` inline replace the scope user for that
event, so beforeSend puts the signed-in backend id back.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017rhTzZBfBRybucitFXRFMW
|
The latest updates on your projects. Learn more about Vercel for GitHub. 2 Skipped Deployments
|
Code reviewNo issues found. Checked for bugs and CLAUDE.md compliance. Review scope:
🤖 Generated with Claude Code |
This branch has not been deployed
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
The app now reports the errors users actually see to the new admin Errors page. Events are batched to
POST <EXPO_PUBLIC_FLASH_API_BASE_URL>/accounts/v1/errors/ingest.What is reported (
lib/telemetry/)track()of a failure event, such as "Deposit Failed" or "Email Verification Failed".amplitudeoption.error_boundaryis skipped because the boundary reports crashes itself.Toast.showis wrapped, and everyerrortoast is reported with the text the user saw.fetchwrapper covers calls to our 4 backend base URLs only, never to third parties or to the ingest endpoint.ErrorBoundaryreports the crash with the screen and the linked GlitchTip event id. A stale web bundle is reported asSTALE_BUNDLEat info level, not as a crash.How it's sent
errorIngestQueueflushes every 2 s or at 20 events, sending at most 50 per batch.keepaliveonpagehide.userIdonly from the session, never from the body.__DEV__). Turn it off elsewhere withEXPO_PUBLIC_ERRORS_INGEST_ENABLED=false; it is on by default.GlitchTip now knows the user.
sentryUsersets the scope user to the backend user id and username, never the email, followinguseUserStore.beforeSendmakes that id win over captures that still pass a Turnkey sub-org id inline.sendDefaultPiistaysfalse, so no IP, headers or cookies are sent. This is a deliberate change from "no user identifiers in GlitchTip": it is how the Errors page links a crash to a user. Please confirm you're happy with it.lib/utils/userFacingError.ts(and its test) is copied verbatim frommaster. It is not onqayet, and the reporters use itsredactSecrets,isNetworkErroranduserFacingErrorMessage.git diff origin/master -- lib/utils/userFacingError.tsis empty, so it will merge cleanly whenmasteris next merged intoqa.Depends on
Solid-Money/solid-backend#1953 serves the ingest endpoint. Shipping this first is safe:
ERRORS_ENABLEDunset, as on prod) answers202 { accepted: 0 }.Testing
lib/telemetry/__tests__andlib/utils/__tests__, all passing. They cover the queue, redaction, flow inference, the fetch and toast reporters, and the Sentry user sync.tsc: no new errors; the 9 pre-existing ones onqaremain.eslintis clean on the changed files.qa.🤖 Generated with Claude Code
https://claude.ai/code/session_017rhTzZBfBRybucitFXRFMW