Skip to content

feat(l10n): report whole-bundle l10n load failures to Sentry - #21044

Open
LZoog wants to merge 1 commit into
mainfrom
l10n-prod-bug-reporting
Open

feat(l10n): report whole-bundle l10n load failures to Sentry#21044
LZoog wants to merge 1 commit into
mainfrom
l10n-prod-bug-reporting

Conversation

@LZoog

@LZoog LZoog commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Because

  • FXA-14361 highlighted a a bug that served English to every locale in production
  • The client emits no telemetry when an l10n bundle fails to load, so a whole-bundle outage is indistinguishable from a working page unless someone reads the copy.

This pull request

  • Adds a reportBundleError prop to AppLocalizationProvider, fired when a bundle has no manifest entry, returns a non-OK status, or the manifest itself cannot be loaded.
  • Sends those failures to Sentry tagged area: 'l10n' with the failing locale, deduped by message and capped at 10 per page load.
  • Buffers reports until sentryMetrics.enable() runs, flushing from the same effect in App that enables it.
  • Returns an empty bundle rather than a non-OK response body, which Fluent would otherwise parse as junk.
  • Leaves individual missing string ids with Fluent's console reporter.
  • Fixes the test manifest fixture, which was invalid JSON with leading-slash keys that never matched the path the provider computes.

Issue that this pull request solves

Closes: FXA-14362

Checklist

Put an x in the boxes that apply

  • My commit is GPG signed.
  • If applicable, I have modified or added tests which pass locally.
  • I have added necessary documentation (if appropriate).
  • I have verified that my changes render correctly in RTL (if appropriate).
  • I have manually reviewed all AI generated code.

How to review (Optional)

  • Key files/areas to focus on: the buffer/flush in l10n-error-reporter.ts, and the three report sites in AppLocalizationProvider.tsx.
  • Suggested review order: AppLocalizationProvider.tsxl10n-error-reporter.tsApp/index.tsxindex.tsx.
  • Risky or complex parts: the reporter holds page-lifetime module state (dedup set, buffer, enabled flag). DynamicLocalizationContext.tsx is a two-line change plus a whole-file reformat from the pre-commit prettier hook.

Screenshots (Optional)

Please attach the screenshots of the changes made in case of change in user interface.

Other information (Optional)

  • Split out of fix(settings): order l10n bundling before static asset hashing #21043 so the outage fix there stays a two-file diff. The two are independent and share no files.
  • Sampling was deliberately left out. Bundle-level reporting plus dedup is expected to produce 1–3 events per affected session, so volume is better tuned in Sentry than by risking the first report of a new failure.
  • Buffering is load-bearing, not defensive: beforeSend drops events while Sentry is disabled, and AppLocalizationProvider resolves bundles before App can mount, so without it the feature would report nothing.
  • The fixture fix was verified by pointing a mapping value at a path fetch-mock does not serve — the existing tests passed either way beforehand, so a green suite did not prove the mapping was being consulted.

Because:

- A build regression shipped a manifest with no main.ftl entries, and every
  locale silently fell back to English for several releases.
- Nothing surfaced it: the client logs one console warning per string and
  emits no telemetry, so it had to be spotted by eye.

This commit:

- Adds a reportBundleError prop to AppLocalizationProvider, fired when a
  bundle has no manifest entry, returns a non-OK status, or the manifest
  itself cannot be loaded.
- Sends those to Sentry tagged area:l10n, deduped by message and capped per
  page load. Individual missing string ids stay with Fluent's reporter.
- Buffers reports until sentryMetrics.enable() runs, since bundles resolve
  before App mounts and Sentry drops events until then.
- Returns an empty bundle rather than a non-OK response body, which Fluent
  would otherwise parse as junk.
- Fixes the test manifest fixture, which was invalid JSON with keys that
  never matched the computed path.

Closes #FXA-14362
@LZoog

LZoog commented Aug 14, 2026

Copy link
Copy Markdown
Contributor Author

This was pulled out of #21043

@LZoog
LZoog marked this pull request as ready for review August 14, 2026 20:40
@LZoog
LZoog requested a review from a team as a code owner August 14, 2026 20:40
Copilot AI balanced review requested due to automatic review settings August 14, 2026 20:40

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

Adds Sentry reporting for whole-bundle localization failures while respecting metrics consent.

Changes:

  • Detects manifest, mapping, HTTP, and fetch failures.
  • Buffers, deduplicates, and caps Sentry reports.
  • Adds localization and reporter tests.

Reviewed changes

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

Show a summary per file
File Description
packages/fxa-settings/src/lib/l10n-error-reporter.ts Buffers and submits capped Sentry reports.
packages/fxa-settings/src/lib/l10n-error-reporter.test.ts Tests buffering, deduplication, and limits.
packages/fxa-settings/src/index.tsx Connects localization failures to the reporter.
packages/fxa-settings/src/contexts/DynamicLocalizationContext.tsx Forwards the error callback.
packages/fxa-settings/src/components/App/index.tsx Flushes reports after enabling Sentry.
packages/fxa-react/lib/AppLocalizationProvider.tsx Detects and reports bundle-loading failures.
packages/fxa-react/lib/AppLocalizationProvider.test.tsx Tests manifest and bundle failures.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.


// The locale is read now rather than at flush time, since a language switch
// can happen in between.
const report = { error, locale: document.documentElement.lang };
Comment on lines +51 to +53
// A well-formed manifest, served under its own baseDir so it does not
// collide with the invalid-manifest fixture above. `farewells` is
// deliberately absent from it, and `notfound` maps to a path that 404s.
sentryMetrics.enable();
// l10n bundles are fetched before this component can mount, so any
// failure there is buffered until Sentry will accept it.
flushL10nErrorReports();
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.

2 participants