Skip to content

Set anonymous Sentry user so alerts report users affected#2840

Merged
piyalbasu merged 2 commits into
masterfrom
fix/sentry-set-user-id
Jun 12, 2026
Merged

Set anonymous Sentry user so alerts report users affected#2840
piyalbasu merged 2 commits into
masterfrom
fix/sentry-set-user-id

Conversation

@piyalbasu

Copy link
Copy Markdown
Contributor

TL;DR

Sentry alerts for the Freighter extension all showed "Users: 0", so we couldn't tell how many people a given error actually affected. The cause: error events were never tagged with a user, so Sentry had no one to count. This attaches a stable, anonymous per-install identifier to Sentry events (only when error reporting is already enabled), so alerts now show real "users affected" counts. No personal data or wallet addresses are involved — it's the same opaque ID analytics already uses, so the two stay in agreement. This matches how the mobile app already works.

Implementation details (for agents)

Root cause: @sentry/browser is on v9, where sendDefaultPii defaults to false (no IP capture), and Sentry.init was never followed by a Sentry.setUser call. Every event therefore arrived with an empty user, and Sentry's "users affected" counts distinct user identifiers → 0.

What changed:

  • Attach an anonymous user id during Sentry init, inside the existing SENTRY_KEY && isDataSharingAllowed consent gate, reusing the persisted analytics id (same one Amplitude uses, so counts stay aligned):

    });
    // Attach a stable anonymous user ID so Sentry can report "users
    // affected" counts. Reuses the same persisted random ID as Amplitude
    // (helpers/metrics getUserId) so user counts stay aligned across the two.
    // No PII / wallet address — just an opaque per-install identifier.
    // Mirrors freighter-mobile's Sentry.setUser in src/components/App.tsx.
    Sentry.setUser({ id: getUserId() });

  • Export the existing getUserId helper so the Sentry init can reuse it rather than minting a separate id:

    export const getUserId = (): string => {

  • Harden the id generator: Math.random() can yield values < 1e-6 (rendered in exponential notation, e.g. "4e-7") or exactly 0 ("0"), where split(".")[1] is undefined. That undefined would flow into Sentry.setUser({ id: undefined }) and amplitude.setUserId(undefined), reproducing "Users: 0" for that install. Fall back to "0":

    const generateRandomUserId = (): string =>
    // Math.random() can yield values < 1e-6 (exponential notation, e.g. "4e-7")
    // or exactly 0 ("0"), where `split(".")[1]` is undefined. Fall back to "0"
    // so we never persist or hand Sentry/Amplitude an undefined user id.
    Math.random().toString().split(".")[1] ?? "0";

Design notes:

  • Gated on consent — only set inside the existing data-sharing check, and cleared by the existing Sentry.close() on opt-out.
  • No PII — opaque random id, never the public key / wallet address. Same metrics_user_id localStorage key as Amplitude, so Sentry and Amplitude user counts agree.
  • Mirrors freighter-mobile, which already does Sentry.setUser({ id: await getUserId() }) in src/components/App.tsx off the same shared getUserId.

Verification:

  • tsc --noEmit -p extension/tsconfig.json → exit 0, 0 errors.
  • Pre-commit hooks (lint + i18next-scanner) passed.
  • Behavior is forward-only: existing open issues stay at 0 affected users; counts populate as new events arrive from updated installs.

Follow-up / out of scope:

  • The same generateRandomUserId undefined edge case exists in freighter-mobile's generator; worth the same one-line ?? "0" hardening in that repo as a separate PR.

Sentry alerts showed "Users: 0" because no user context was ever
attached to events. On @sentry/browser v9, sendDefaultPii defaults to
false (no IP), and the extension never called Sentry.setUser, so every
event arrived with an empty user and could not be attributed.

Attach the existing persisted anonymous analytics id (the same one
Amplitude uses) via Sentry.setUser, gated on the existing data-sharing
consent. No PII or wallet address — just an opaque per-install id, so
Sentry and Amplitude user counts stay aligned. Mirrors freighter-mobile.

Also harden generateRandomUserId: Math.random() can yield values < 1e-6
(exponential notation) or exactly 0, where split(".")[1] is undefined;
fall back to "0" so we never hand Sentry/Amplitude an undefined id.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings June 11, 2026 23:33

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 459c3afc47

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread extension/src/popup/components/ErrorTracking/index.tsx
@github-actions

github-actions Bot commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

PR Preview build is ready: https://github.com/stellar/freighter/releases/tag/untagged-2ff63a035bea038feea7 (SDF collaborators only — install instructions in the release description)

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the extension’s Sentry initialization to attach a stable, anonymous per-install user identifier to error events (only when data sharing is enabled), allowing Sentry alerts to correctly show “users affected” counts.

Changes:

  • Set a Sentry user { id } during Sentry initialization using the existing persisted analytics user ID.
  • Export getUserId from helpers/metrics so it can be reused by error tracking.
  • Harden the random ID generator to avoid producing undefined in edge cases (Math.random() exponential/zero formatting).

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
extension/src/popup/components/ErrorTracking/index.tsx Sets an anonymous Sentry user ID during init so Sentry can compute “users affected”.
extension/src/helpers/metrics.ts Exports getUserId and hardens ID generation to avoid undefined IDs.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread extension/src/popup/components/ErrorTracking/index.tsx
Comment thread extension/src/helpers/metrics.ts
…mock

- Clear the per-install user id (Sentry.setUser(null)) before Sentry.close
  on data-sharing opt-out. Sentry.close may still report (anonymized) until
  the next refresh; without this those reports would keep the id attached.
- Add getUserId to the helpers/metrics jest mock in setupTests so rendering
  ErrorTracking under test doesn't call an undefined mock.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@piyalbasu piyalbasu merged commit 21b6e38 into master Jun 12, 2026
11 checks passed
@piyalbasu piyalbasu deleted the fix/sentry-set-user-id branch June 12, 2026 15:19
@github-actions github-actions Bot mentioned this pull request Jun 15, 2026
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.

3 participants