Skip to content

RI-8113 Add Sentry error tracking for the Electron app#6073

Merged
KrumTy merged 61 commits into
mainfrom
feature/RI-8113/sentry-tracking
Jun 23, 2026
Merged

RI-8113 Add Sentry error tracking for the Electron app#6073
KrumTy merged 61 commits into
mainfrom
feature/RI-8113/sentry-tracking

Conversation

@KrumTy

@KrumTy KrumTy commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

What

Integrates Sentry error tracking for the Electron app (main + renderer) and the web build (RI-8113).

  • Consent-gated, two-tier reporting. Without analytics consent only an anonymous, minimal allowlist is sent (mirrors the existing non-tracking APPLICATION_STARTED model); with consent, full events that are still scrubbed. A shared, SDK-agnostic scrubbing module strips sensitive fields, drops IP / server_name, and normalizes file paths. Consent is plumbed renderer → main over IPC and cached for an early-boot decision.
  • Native crash reporting (Electron crashReporter minidumps) starts only after consent (start-once; cannot be scrubbed).
  • Redesigned ErrorBoundary split into component / types / styles / constants / utils, with a thin SentryErrorBoundary wrapper that reports to Sentry. The renderer SDK's IPC bridge is set up via @sentry/electron/preload so renderer-side errors actually reach the main process.
  • Source-map upload via the Sentry vite + webpack plugins using debug-ID matching (release = app version, bundles labeled by build OS via dist). Maps are hidden and deleted after upload, so they never ship. Gated on RI_SENTRY_AUTH_TOKEN + RI_SENTRY_ENABLED → prod builds only; upload failures are non-fatal.
  • Events tagged by app.layer (electron-main / electron-renderer / web).
  • Fully env-gated — unset/false RI_SENTRY_ENABLED or a missing DSN makes Sentry a no-op (e.g. the RedisInsight-Cloud repo can disable it).

CI configuration required

  • Repository variables: RI_SENTRY_ENABLED, RI_SENTRY_ORG, RI_SENTRY_PROJECT
  • Repository secret: RI_SENTRY_DSN
  • Production-environment secret: RI_SENTRY_AUTH_TOKEN (source-map upload; prod builds only — dev builds still report, but ship no maps)

Note

@sentry/* is locked to @sentry/react 10.39.0 / @sentry/electron 7.8.0 in the lockfile; newer 10.50+/7.13 resolutions introduce a duplicate @sentry/core and a type error. Don't bump without re-running yarn type-check.

Testing

  • Build the desktop app with RI_SENTRY_ENABLED=true and RI_SENTRY_DSN set; trigger a renderer error (error boundary) and a main-process error and confirm both reach Sentry, tagged electron-renderer / electron-main.
  • Companion branch feature/RI-8113/sentry-tracking-crash adds crash-trigger helpers for manual verification (kept in sync from this branch).
  • Unit tests: scrubbing.spec.ts (scrubbing + Tier-1 minimization) and ErrorBoundary.spec.tsx.

Closes RI-8113


Note

Medium Risk
Touches crash reporting, consent-gated telemetry, and CI secrets; misconfiguration could leak richer data without consent or ship source maps if upload cleanup fails (mitigated in code).

Overview
Adds Sentry end-to-end for the desktop app (main + renderer) and the web UI, gated on RI_SENTRY_ENABLED and RI_SENTRY_DSN.

Runtime: Early initSentry() in main (app.ts), web (index.tsx), and Electron renderer (indexElectron.tsx); preload imports @sentry/electron/preload for renderer IPC. Main process uses consent-aware beforeSend / beforeBreadcrumb, strips minidump/session integrations that bypass consent, and toggles Electron crashReporter (enabled in config.json) only when analytics consent is granted via new IPC setSentryConsent + useSentryConsentSync. Renderer/web mirror the same pattern with checkIsAnalyticsGranted() and shared scrubEvent / minimizeEvent helpers.

UX: Generic ErrorBoundary plus SentryErrorBoundary wrap web and Electron roots; config gains a sentry block from env.

Build/CI: Docker, Linux, macOS, and Windows pipelines pass RI_SENTRY_* vars/secrets. Vite and webpack Sentry plugins upload hidden source maps when enabled + auth token, then delete maps (failed uploads also rimraf so maps never ship). UI build gets extra heap via cross-env NODE_OPTIONS.

Reviewed by Cursor Bugbot for commit 0a3ba64. Bugbot is set up for automated code reviews on this repo. Configure here.

KrumTy and others added 30 commits June 11, 2026 10:55
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
A synchronous throw inside the globalShortcut callback is swallowed by
Electron's native dispatch and never reaches Sentry's uncaughtException
handler, so Cmd/Ctrl+Shift+K reported nothing. Capture the error
explicitly instead, matching the shortcut's non-crashing intent.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Two-tier consent model inside Sentry (anonymous Tier 1 / consented Tier 2),
scrubbing security-review checklist, early-crash + consent-caching handling,
and mapping to the RI-8113 scope. Intended for Legal/Security review.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Tier-1 allowlist accepted; IP not tracked; region confirmation pending
(EU recommended); retention defaulted to 90 days.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ing)

Org is US-region (per DSN host). Region is fixed at org creation, so Legal
should confirm US is acceptable for anonymized crash data, or an EU org must
be created before launch.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sentry is an org-approved vendor; all data stored in US. No EU org needed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Implements the consent model from docs/sentry-production-readiness.md:

- Shared, SDK-agnostic scrubbing module (ui/src/services/sentry) used by
  both the main process and renderer so the layers cannot drift:
  scrubEvent (redacts extra/contexts/request/breadcrumbs, normalizes
  stack-frame paths, strips server_name/IP) + minimizeEvent (Tier 1
  anonymous allowlist under a shared sentinel id).
- Main process: default-deny consent flag cached in electron-store for a
  synchronous boot read; beforeSend sends full (scrubbed) events with
  consent and minimized anonymous events without; breadcrumbs gated on
  consent; native crashReporter upload gated behind consent (start-once);
  setConsent() updates the tier at runtime.
- Renderer: beforeSend self-gates per-event via checkIsAnalyticsGranted.
- Consent plumbing: useSentryConsentSync pushes agreements.analytics to
  the main process over IPC (setSentryConsent) on startup and on toggle.
- Unit tests for the scrubbing module.

Note: autoSessionTracking/serverName options dropped where the Sentry v10
type no longer accepts them (renderer); server_name is cleared per-event.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The PoC added a predicate function into rollup's `external` array, which
only accepts string | RegExp — a TS2769 overload error surfaced after the
rebase pulled in newer vite/rollup types. Fold the module list, regex
patterns, and the api-dist predicate into a single `external` function
(behavior-preserving).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@redis-ui/components v44 (pulled in by the rebase) imports icons via
subpaths, e.g. @redislabsdev/redis-ui-icons/multicolor. The moduleNameMapper
matched only the bare package name and dropped the subpath, so the mapped
module resolved to the package root and LoaderLargeIcon was undefined —
styled(undefined) crashed every UI test suite at setup. Anchor each mapping
and capture the optional subpath ($1) so deep imports survive the rename.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Make the title the visual focal point (was small/faded vs the button),
mute the supporting copy, and replace the alarming brand-red action with
the calm primary blue (recovery, not crash). Colors are theme-aware via
the persisted document.body theme class and mirror redis-ui neutral/
primary tokens — inlined because the boundary renders above ThemeProvider,
where useTheme()/themed CSS variables are unavailable when a crash is caught.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Separate the generic ErrorBoundary (catch + fallback UI + onError callback)
from SentryErrorBoundary (a thin wrapper that injects Sentry reporting).

Fixes a real robustness gap: the Sentry capture call previously ran
unguarded in componentDidCatch, so if it threw, the error escaped the
boundary and the fallback UI never rendered. ErrorBoundary now invokes
onError inside try/catch, so a reporting failure can never prevent the
fallback from showing. The generic boundary is also reusable/testable
without any Sentry dependency.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Follow the component-folder convention: extract ErrorBoundaryProps/State
and Palette to .types.ts, the inline CSSProperties to .styles.ts, the
palettes + copy to .constants.ts, and getPalette to .utils.ts. The
component file is now just the boundary logic + markup.

Styles stay plain CSSProperties (not styled-components) because the
boundary renders above ThemeProvider; the rationale lives in the
constants/styles file headers.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Cover the fallback rendering, custom fallback, onError forwarding, and the
robustness guarantee that the fallback still renders when onError throws.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…IDs)

Record §9: source maps are required for real debugging value; decision is
release=pkg.version (no per-build SHA) + debug IDs for bundle/map matching,
SHA as metadata only. Captures current build state, implementation outline,
and the build-determinism open question. Also mark ErrorBoundary refinement
done.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add @sentry/vite-plugin (renderer) and @sentry/webpack-plugin (main),
gated on SENTRY_AUTH_TOKEN so they are a no-op for local/dev builds. When
the token is present (CI) they generate hidden source maps, inject debug
IDs into bundle+map, upload to Sentry, and delete the maps so they never
ship in the app. Release name = pkg.version (matches the runtime release);
debug IDs handle bundle/map matching, so no per-build SHA is needed.

Wire the env vars into all four build pipelines, and add the missing
RI_SENTRY_UI_DSN (the renderer Sentry layer reads it but it was never
passed). New CI config required (see readiness doc): SENTRY_AUTH_TOKEN
(secret), SENTRY_ORG / SENTRY_PROJECT_UI / SENTRY_PROJECT_ELECTRON (vars),
and the RI_SENTRY_UI_DSN secret.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…vars

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1. Prefix the source-map env vars with RI_ for consistency:
   RI_SENTRY_AUTH_TOKEN / RI_SENTRY_ORG / RI_SENTRY_PROJECT_UI /
   RI_SENTRY_PROJECT_ELECTRON (vite + webpack configs and all four
   pipelines). Note: the auth token is build-time only and must never be
   read via import.meta.env in client code.

2. Initialize Sentry in the web entry (index.tsx) via a new
   services/sentryWeb.ts using @sentry/react, mirroring the Electron
   renderer (consent-gated two-tier reporting, shared scrubbing). All three
   targets now report: Electron main, Electron renderer, and web/docker.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
A PoC commit (link electron sentry project) repointed the UI sentry.dsn at
RI_SENTRY_ELECTRON_DSN, so the renderer and web reported to the Electron
project and RI_SENTRY_UI_DSN was never read. Point it back at the UI DSN.

Also document that this sentry block is runtime-overridable per host via the
domainConfig merge in config/index.ts — the channel the cloud deployment
will use to point the web build at its own Sentry project (no refactor of
the init code needed).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Capture that this PR is forward-compatible with the cloud runtime-config
approach (getConfig deep-merges per-host domainConfig; init reads config not
env; sync resolution = no re-init), the additive cloud work, and the exact
integration point. Records that cloud serves a prebuilt S3 web artifact.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Consolidate the split RI_SENTRY_ELECTRON_DSN / RI_SENTRY_UI_DSN into one
RI_SENTRY_DSN shared by the Electron main process, renderer, and web — one
Sentry project, filtered by platform/environment within it (no second
project to maintain). Update the main init, UI config, webpack
EnvironmentPlugin, all four pipelines, and the readiness doc. Also drop the
redundant source-map comment lines from the workflow env blocks.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
With one Sentry project, the renderer and main source-map uploads target
the same project. Collapse RI_SENTRY_PROJECT_UI / RI_SENTRY_PROJECT_ELECTRON
into a single RI_SENTRY_PROJECT (vite + webpack configs, all four pipelines,
doc).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The webpack EnvironmentPlugin defaulted RI_SENTRY_ENVIRONMENT to 'production'
while the runtime code and UI config default to 'development'. Align it to
'development' and fix the stale doc comment.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Keep the readiness/planning doc local-only (added to .git/info/exclude),
like docs/pr-plan-RI-7682-decouple-fe-be.md. It should not land in the PR.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Main process now enables Sentry on 'true' OR '1', matching the renderer/web
  booleanEnv semantics, so the two layers no longer diverge when
  RI_SENTRY_ENABLED=1 (main was strict-'true' only).
- Add normalizePath regression tests for C:/Users/... and
  file:///C:/Users/... — the /Users/ branch already normalizes these
  (prefix-agnostic); the tests lock it in against regex regressions.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Comment thread redisinsight/ui/src/services/sentryElectron.ts Outdated
Comment thread configs/webpack.config.main.prod.ts Outdated

@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: 13eff86766

ℹ️ 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 redisinsight/ui/src/services/sentry/scrubbing.ts Outdated
Comment thread redisinsight/ui/vite.config.mjs Outdated
…en scrubbing

- Source-map upload gates (vite + webpack) now accept RI_SENTRY_ENABLED='1' as
  well as 'true', matching the runtime/booleanEnv semantics so a build
  configured with '1' still symbolicates (previously: events on, maps off).
- Free-text scrubber now redacts Bearer/Basic auth scheme credentials and
  OAuth-prefixed token names (access_token, refreshToken, ...), which the
  previous assignment pattern missed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

@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: 65bd50da9d

ℹ️ 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 redisinsight/ui/src/services/sentryWeb.ts Outdated
Comment thread redisinsight/ui/src/services/sentryElectron.ts Outdated
Comment thread redisinsight/desktop/src/lib/sentry/sentry.ts
Default session integrations emit release-health envelopes on load/navigation
that are NOT events, so they bypass the beforeSend consent gate and would send
usage telemetry for opted-out users. Disable them in all three layers:
- web + Electron renderer: BrowserSession
- main: MainProcessSession

Also align the Electron renderer's `release` to riConfig.app.version (same
source as the web init and the Vite upload plugin) for consistency.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

@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: 514ca30562

ℹ️ 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 redisinsight/ui/vite.config.mjs
filesToDeleteAfterUpload only runs after a successful upload, and the upload
errorHandler is intentionally non-fatal — so a failed upload (bad token, 5xx,
network) left the emitted .js.map files in the output dir to be packaged.
Delete them in the errorHandler too (both vite + webpack) so maps never ship
regardless of upload outcome.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

@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: 02e83f18e0

ℹ️ 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 redisinsight/ui/src/services/sentry/scrubbing.ts Outdated
Comment thread redisinsight/ui/src/services/sentry/scrubbing.ts Outdated
KrumTy and others added 2 commits June 17, 2026 11:13
minimizeEvent dropped debug_meta and minimizeFrame dropped abs_path, so
no-consent (Tier-1) events could not be matched to uploaded source maps and
showed minified frames. Keep debug_meta (code_file + debug_id) and abs_path,
normalizing any user path defensively. These carry no PII — build paths +
debug-id UUIDs — so anonymous stacks become readable without weakening the
Tier-1 redaction.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… request url

scrubSensitiveData only redacts by key name, so a secret inside a string value
(e.g. a token/credential in a breadcrumb's data.url) passed through on the
consented path. Add scrubSecretsDeep, applied to extra/contexts/request/
breadcrumb data, so string values are also free-text scrubbed. Also run
normalizePath over request.url to strip an OS account name from a Windows
file:// page URL (matching how stack-frame paths are handled).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

@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: e30d40fdbf

ℹ️ 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 redisinsight/desktop/src/lib/sentry/sentry.ts
Electron's crashReporter is unsupported under the MAS App Sandbox. Guard
process.mas in initCrashReporter so MAS builds skip native minidumps while
JS-level Sentry reporting continues to work.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Comment thread redisinsight/ui/src/services/sentry/scrubbing.ts
Comment thread redisinsight/ui/src/components/error-boundary/ErrorBoundary.constants.ts Outdated
@KrumTy KrumTy requested a review from valkirilov June 23, 2026 07:52
Comment thread redisinsight/ui/src/services/hooks/useSentryConsentSync.ts
valkirilov
valkirilov previously approved these changes Jun 23, 2026
Comment thread redisinsight/desktop/src/lib/sentry/sentry.ts Outdated
Comment thread redisinsight/ui/index.tsx
Addresses review feedback on the PR:
- Trim comments across the Sentry modules to short why-only notes (per the
  comments rule in #6091); drop how/story comments and stale doc references.
- Wrap Sentry.init in try/catch in the web and Electron-renderer initSentry
  (matching the main process) so a Sentry init failure can't break app startup.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

@cursor cursor 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.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 0a3ba64. Configure here.

@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: 0a3ba64346

ℹ️ 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 redisinsight/ui/src/services/sentry/scrubbing.ts
Comment thread redisinsight/ui/src/services/sentry/scrubbing.ts
@KrumTy KrumTy merged commit 743be2b into main Jun 23, 2026
30 checks passed
@KrumTy KrumTy deleted the feature/RI-8113/sentry-tracking branch June 23, 2026 10:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants