Skip to content

feat(frontend): Sentry React SDK + Router v7 tracing + replay - #876

Merged
LucasSantana-Dev merged 3 commits into
release/v2.12.0from
feat/frontend-observability
May 16, 2026
Merged

LucasSantana-Dev merged 3 commits into
release/v2.12.0from
feat/frontend-observability

Conversation

@LucasSantana-Dev

@LucasSantana-Dev LucasSantana-Dev commented May 15, 2026 •

Copy link
Copy Markdown
Owner

Summary

PR D of the observability rollout. Adds browser-side error reporting + performance tracing to the dashboard SPA, completing the data-layer coverage across bot (#873), backend (#875), and frontend.

What

  • Sentry.init on app boot via initSentry() called from main.tsx before React mounts so early errors are captured
  • reactRouterV7BrowserTracingIntegration wired to react-router-dom v7 so route changes become Sentry transactions; LCP / CLS / INP captured automatically per transaction
  • replayIntegration: 10% of sessions, 100% of sessions that hit an error
  • captureFrontendException(err, context?) helper for catch-block reporting where the existing UI already surfaces the error state

Configuration

All optional Vite env vars — missing VITE_SENTRY_DSN makes initSentry a no-op (dev / preview / self-hosted without telemetry):

Env Default Meaning
VITE_SENTRY_DSN — Enables Sentry when set
VITE_SENTRY_ENVIRONMENT import.meta.env.MODE dev / staging / prod
VITE_SENTRY_RELEASE VITE_COMMIT_SHA Release identifier
VITE_SENTRY_TRACES_SAMPLE_RATE 0.1 % of route changes traced
VITE_SENTRY_REPLAYS_SESSION_SAMPLE_RATE 0.1 % of sessions replayed
VITE_SENTRY_REPLAYS_ON_ERROR_SAMPLE_RATE 1.0 % of error sessions replayed

Test plan

  • sentry.test.ts (7 cases):
    • no-op without DSN (privacy-by-default for self-hosted)
    • Sentry.init shape with DSN + env + release
    • Router v7 + replay integrations wired
    • custom sample rates honored
    • default sample rates applied when env missing
    • captureFrontendException with and without extra context
  • Frontend `type:check` clean
  • Frontend `lint` clean (`--max-warnings 0`)
  • Manual: set `VITE_SENTRY_DSN` in `.env.local`, click around, confirm a route-change transaction lands in Sentry

Deployment notes

  • Set `VITE_SENTRY_DSN` (and the rest of the `VITE_SENTRY_*` env, as needed) in the production build secrets / `.env.production`
  • Set `VITE_SENTRY_RELEASE` to the commit SHA from CI so errors are tagged with the right release
  • No DSN exposed at build time → completely off in self-hosted forks unless the operator opts in

Known CI hazard

The yt-dlp postinstall flake (#874) may trip the quality / Lint job. Re-run or land #874's fix first.

Out of scope

Summary by CodeRabbit

Release Notes

  • New Features

    • Integrated error monitoring to automatically capture and report frontend runtime errors
    • Added session replay functionality to record user interactions during application errors, aiding in issue diagnosis
    • Configured environment and release tracking for better error classification and debugging
  • Tests

    • Added test suite validating error monitoring and reporting functionality

Review Change Stack

PR D of the observability rollout. Adds browser-side error reporting +
performance tracing to the dashboard SPA, completing the data-layer
coverage across bot (#873), backend (#875), and frontend.

What
- Sentry.init on app boot via initSentry() called from main.tsx
  before React mounts so early errors are captured
- reactRouterV7BrowserTracingIntegration wired to react-router-dom v7
  so route changes become Sentry transactions (LCP, CLS, INP, INP
  attribution captured automatically per transaction)
- replayIntegration: 10% of sessions, 100% of error sessions

Configuration (all VITE_ env vars, all optional)
- VITE_SENTRY_DSN: enables Sentry. Missing → initSentry is a no-op (dev,
  preview, self-hosted without telemetry)
- VITE_SENTRY_ENVIRONMENT: defaults to import.meta.env.MODE
- VITE_SENTRY_RELEASE: defaults to VITE_COMMIT_SHA
- VITE_SENTRY_TRACES_SAMPLE_RATE (default 0.1)
- VITE_SENTRY_REPLAYS_SESSION_SAMPLE_RATE (default 0.1)
- VITE_SENTRY_REPLAYS_ON_ERROR_SAMPLE_RATE (default 1.0)

Helper
- captureFrontendException(err, context?) for catch-block reporting where
  the existing UI already surfaces the error state

Tests
- sentry.test.ts (7 cases): no-op without DSN, init shape with DSN +
  env + release, integrations wired, custom + default sample rates,
  captureFrontendException with and without context

Out of scope
- Source maps upload (config via @sentry/vite-plugin) — wire in PR E once
  release pipeline is firmed up
- Web Vitals collection beyond what browserTracingIntegration already
  records (web-vitals package not added — Sentry already captures the
  core vitals on the first navigation transaction)
@vercel

vercel Bot commented May 15, 2026 •

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
lucky Ready Ready Preview, Comment May 16, 2026 2:04am

Request Review

@greptile-apps greptile-apps 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.

LucasSantana-Dev has reached the 50-review limit for trial accounts. To continue receiving code reviews, upgrade your plan.

@coderabbitai

coderabbitai Bot commented May 15, 2026 •

Copy link
Copy Markdown

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: a472a111-f53e-4864-8702-914e9df54636

📥 Commits

Reviewing files that changed from the base of the PR and between ea886cc and 8b9e70f.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json, !**/package-lock.json
📒 Files selected for processing (4)
  • packages/frontend/package.json
  • packages/frontend/src/lib/sentry.test.ts
  • packages/frontend/src/lib/sentry.ts
  • packages/frontend/src/main.tsx

📝 Walkthrough

Walkthrough

This PR introduces frontend error tracking via Sentry. It adds the @sentry/react dependency, implements initialization and error capture helpers, provides comprehensive test coverage, and integrates Sentry initialization into the app startup before React renders.

Changes

Frontend Sentry Error Tracking

Layer / File(s) Summary
Sentry module and dependency
packages/frontend/package.json, packages/frontend/src/lib/sentry.ts
Adds @sentry/react dependency and implements initSentry() that reads configuration from Vite environment variables (DSN, environment, release, sample rates), returns early if DSN is absent, and initializes Sentry with React Router v7 tracing and session replay integrations. Also implements captureFrontendException() helper to forward errors to Sentry with optional context.
Sentry module tests
packages/frontend/src/lib/sentry.test.ts
Comprehensive test suite mocking @sentry/react and verifying initSentry() no-op behavior when DSN is missing, correct config wiring for DSN/environment/release/sample-rates, integration loading for React Router v7 and Replay, and captureFrontendException() error forwarding with optional context mapping.
App startup integration
packages/frontend/src/main.tsx
Calls initSentry() before React renders to capture early runtime errors; acts as no-op when DSN is not configured.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/frontend-observability

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

packages/frontend/src/lib/sentry.test.ts

Oops! Something went wrong! :(

ESLint: 10.2.0

Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'eslint-plugin-react-hooks' imported from /packages/frontend/eslint.config.js
at Object.getPackageJSONURL (node:internal/modules/package_json_reader:301:9)
at packageResolve (node:internal/modules/esm/resolve:764:81)
at moduleResolve (node:internal/modules/esm/resolve:855:18)
at defaultResolve (node:internal/modules/esm/resolve:988:11)
at #cachedDefaultResolve (node:internal/modules/esm/loader:697:20)
at #resolveAndMaybeBlockOnLoaderThread (node:internal/modules/esm/loader:714:38)
at ModuleLoader.resolveSync (node:internal/modules/esm/loader:746:52)
at #resolve (node:internal/modules/esm/loader:679:17)
at ModuleLoader.getOrCreateModuleJob (node:internal/modules/esm/loader:599:35)
at ModuleJob.syncLink (node:internal/modules/esm/module_job:162:33)

packages/frontend/src/lib/sentry.ts

Oops! Something went wrong! :(

ESLint: 10.2.0

Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'eslint-plugin-react-hooks' imported from /packages/frontend/eslint.config.js
at Object.getPackageJSONURL (node:internal/modules/package_json_reader:301:9)
at packageResolve (node:internal/modules/esm/resolve:764:81)
at moduleResolve (node:internal/modules/esm/resolve:855:18)
at defaultResolve (node:internal/modules/esm/resolve:988:11)
at #cachedDefaultResolve (node:internal/modules/esm/loader:697:20)
at #resolveAndMaybeBlockOnLoaderThread (node:internal/modules/esm/loader:714:38)
at ModuleLoader.resolveSync (node:internal/modules/esm/loader:746:52)
at #resolve (node:internal/modules/esm/loader:679:17)
at ModuleLoader.getOrCreateModuleJob (node:internal/modules/esm/loader:599:35)
at ModuleJob.syncLink (node:internal/modules/esm/module_job:162:33)

packages/frontend/src/main.tsx

Oops! Something went wrong! :(

ESLint: 10.2.0

Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'eslint-plugin-react-hooks' imported from /packages/frontend/eslint.config.js
at Object.getPackageJSONURL (node:internal/modules/package_json_reader:301:9)
at packageResolve (node:internal/modules/esm/resolve:764:81)
at moduleResolve (node:internal/modules/esm/resolve:855:18)
at defaultResolve (node:internal/modules/esm/resolve:988:11)
at #cachedDefaultResolve (node:internal/modules/esm/loader:697:20)
at #resolveAndMaybeBlockOnLoaderThread (node:internal/modules/esm/loader:714:38)
at ModuleLoader.resolveSync (node:internal/modules/esm/loader:746:52)
at #resolve (node:internal/modules/esm/loader:679:17)
at ModuleLoader.getOrCreateModuleJob (node:internal/modules/esm/loader:599:35)
at ModuleJob.syncLink (node:internal/modules/esm/module_job:162:33)


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions Bot added dependencies Pull requests that update a dependency file frontend size/xl labels May 15, 2026
@github-actions

Copy link
Copy Markdown

Failed to generate code suggestions for PR

LucasSantana-Dev added a commit that referenced this pull request May 16, 2026
)

## Summary

Fixes #874 by:

1. **Bumping the pinned ref of the org reusable \`quality.yml\`** to the
merge commit of
[LucasSantana-Dev/.github#2](LucasSantana-Dev/.github#2).
That PR adds \`GITHUB_TOKEN\` + \`YOUTUBE_DL_SKIP_DOWNLOAD=true\` to the
install step in the \`lint\` and \`deadcode\` jobs, eliminating the 60
req/hr unauthenticated cap that's been failing PRs since the
observability rollout started.

2. **Applying the same env vars to local \`release.yml\`** for parity.
Release builds don't strictly need the yt-dlp binary, so skipping the
fetch is harmless.

## Why this scope

| Workflow | npm ci flags | Status |
|---|---|---|
| \`ci.yml\` | \`--legacy-peer-deps --ignore-scripts\` | already safe |
| \`sonarcloud.yml\` | \`--legacy-peer-deps --ignore-scripts\` | already
safe |
| \`bundle-size.yml\` | runs postinstall | already sets both env vars |
| \`release.yml\` | bare \`npm ci\` | **fixed here** |
| reusable \`quality.yml\` | runs postinstall | **fixed via SHA bump** |

## Closes

- #874

## Unblocks

- PR #873 (bot observability metrics)
- PR #875 (backend observability)
- PR #876 (frontend Sentry)
- PR #877 (paired Lucky-side network for homelab #135)

## Test plan

- [ ] \`quality / Lint\` passes on this PR's first run
- [ ] After merge: re-run failed \`quality / Lint\` on #873 / #875 /
#876 — they should pass without retry

@greptile-apps greptile-apps 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.

LucasSantana-Dev has reached the 50-review limit for trial accounts. To continue receiving code reviews, upgrade your plan.

vi.fn() with no args defaults to a zero-arg signature; the forwarding
wrappers in vi.mock spread `...args: unknown[]` into the mocks, which
TS2556's because the inferred parameter list doesn't accept rest args.

Widen each mock to `(...args: unknown[]) => unknown` so the forwarders
typecheck without changing runtime behavior.

Caught by quality / Lint + compressed-size + Vercel — all three share
the same root cause (tsc failure cascades into build).

@greptile-apps greptile-apps 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.

LucasSantana-Dev has reached the 50-review limit for trial accounts. To continue receiving code reviews, upgrade your plan.

@LucasSantana-Dev
LucasSantana-Dev merged commit 3491eb8 into release/v2.12.0 May 16, 2026
17 of 21 checks passed
@LucasSantana-Dev
LucasSantana-Dev deleted the feat/frontend-observability branch May 16, 2026 02:03
@github-actions

Copy link
Copy Markdown

Size Change: 0 B

Total Size: 422 kB

ℹ️ View Unchanged
Filename Size
packages/frontend/dist/assets/ActionPanel-BJm2-UwJ.js 401 B
packages/frontend/dist/assets/Admin-Cyx3qV4m.js 1.99 kB
packages/frontend/dist/assets/api-AUPUM2Qa.js 3.37 kB
packages/frontend/dist/assets/authStore-D18Icsqi.js 559 B
packages/frontend/dist/assets/AutoMessages-CMmB2nQX.js 2.68 kB
packages/frontend/dist/assets/AutoMod-IIkWFCyV.js 4.09 kB
packages/frontend/dist/assets/badge-BKfLlLik.js 498 B
packages/frontend/dist/assets/Card-DHfizKnr.js 506 B
packages/frontend/dist/assets/Changelog-Bzb0gps0.js 26.6 kB
packages/frontend/dist/assets/CommandsConfig-C9m8Jowf.js 1.47 kB
packages/frontend/dist/assets/Config-CNGVeQEL.js 1.72 kB
packages/frontend/dist/assets/CustomCommands-DUWlpKZm.js 2.16 kB
packages/frontend/dist/assets/DashboardOverview-DjFB3k-Y.js 3.93 kB
packages/frontend/dist/assets/dialog-D4GXigsF.js 948 B
packages/frontend/dist/assets/Docs-DlizujZO.js 17.6 kB
packages/frontend/dist/assets/DocsShell-CcljC3vb.js 1.42 kB
packages/frontend/dist/assets/EmbedBuilder-C9Zm2P7k.js 3.34 kB
packages/frontend/dist/assets/Features-CTsJFBTt.js 754 B
packages/frontend/dist/assets/GuildAutomation-BkkcqQ-5.js 2.92 kB
packages/frontend/dist/assets/guildStore-il-poOxg.js 791 B
packages/frontend/dist/assets/index-B6IXjcnV.css 17.6 kB
packages/frontend/dist/assets/index-eFskPvjF.js 53.9 kB
packages/frontend/dist/assets/input-DFOdST7m.js 465 B
packages/frontend/dist/assets/label-CHNOsjRF.js 488 B
packages/frontend/dist/assets/Landing-DS5COV02.js 5.07 kB
packages/frontend/dist/assets/LastFm-BpjclAYg.js 1.74 kB
packages/frontend/dist/assets/legalNav-Dg0pcNaV.js 270 B
packages/frontend/dist/assets/Levels-Cwq3UvvY.js 2.63 kB
packages/frontend/dist/assets/Login-Djv5bPUR.js 2.5 kB
packages/frontend/dist/assets/Lyrics-h-V2IrJO.js 1.33 kB
packages/frontend/dist/assets/Moderation-CX9QU1JK.js 3.85 kB
packages/frontend/dist/assets/Music-DMqcd96v.js 7.09 kB
packages/frontend/dist/assets/MusicConfig-CQYyqa3R.js 1.61 kB
packages/frontend/dist/assets/PreferredArtists-QvjX_VBy.js 3.76 kB
packages/frontend/dist/assets/PrivacyPolicy-Dj58jJqO.js 1.77 kB
packages/frontend/dist/assets/ReactionRoles-DJU4ywNC.js 1.89 kB
packages/frontend/dist/assets/rolldown-runtime-BYbx6iT9.js 471 B
packages/frontend/dist/assets/SectionHeader-D6idj02z.js 893 B
packages/frontend/dist/assets/select-Bo9ZxOQ5.js 1.23 kB
packages/frontend/dist/assets/ServerLogs-xpeRhEqQ.js 2.91 kB
packages/frontend/dist/assets/ServerSettings-UfbcIO3v.js 4.21 kB
packages/frontend/dist/assets/ServersPage-CpgN-80x.js 2.92 kB
packages/frontend/dist/assets/shim-Qmczh487.js 510 B
packages/frontend/dist/assets/Skeleton-BJSvKI8c.js 236 B
packages/frontend/dist/assets/Spotify-hp1neso5.js 1.75 kB
packages/frontend/dist/assets/Starboard-Bvvb_b68.js 2.08 kB
packages/frontend/dist/assets/StatTile-DQ3lYBMP.js 636 B
packages/frontend/dist/assets/switch-C5G39PBt.js 544 B
packages/frontend/dist/assets/TermsOfService-DFdRongw.js 1.61 kB
packages/frontend/dist/assets/TrackHistory-CBCxIeII.js 2.17 kB
packages/frontend/dist/assets/TwitchNotifications-3ItXaqam.js 2.44 kB
packages/frontend/dist/assets/useActiveHeading-BmLnT6P1.js 1.35 kB
packages/frontend/dist/assets/useFeatures-BTKzapaa.js 2.06 kB
packages/frontend/dist/assets/usePageMetadata-DVjH87aq.js 329 B
packages/frontend/dist/assets/utils-Denu3VwY.js 146 B
packages/frontend/dist/assets/vendor-forms-VJTTJemd.js 25.6 kB
packages/frontend/dist/assets/vendor-radix-DKbKEiWx.js 38.9 kB
packages/frontend/dist/assets/vendor-react-DNaNL-Gj.js 55.6 kB
packages/frontend/dist/assets/vendor-state-B_fYO9zl.js 24.1 kB
packages/frontend/dist/assets/vendor-ui-23gi6Zpr.js 65.5 kB

compressed-size-action

@sonarqubecloud

Copy link
Copy Markdown

LucasSantana-Dev added a commit that referenced this pull request May 21, 2026
## Summary

Cut v2.13.0 of Lucky. Bumps root + 4 workspaces from `2.11.0` → `2.13.0`
(skipping the archived `2.12.0`) and promotes the CHANGELOG
`[Unreleased]` block to `[2.13.0] - 2026-05-21`.

## Headline changes since v2.11.0

**Added**
- Guild Automation Module Executor seam + AutoMessages pilot (#901)
- Sentry React SDK + Router v7 tracing/replay on frontend (#876)
- Prometheus `/metrics` on backend (#875) + bot (#873)
- Guild join/leave history tracking (#872)
- Trivy image-scan on docker-publish, Phase A audit-only (#883)
- Self-hosted developer-tooling register on landing page (#868)

**Changed**
- Backend migrated to Zod 4 API (#919) — unblocked the CVE patch + ended
the lockfile fragility loop
- 3 bot circular-deps clusters broken (#885, #886, #888)

**Fixed**
- brace-expansion DoS + ws uninit-memory CVEs patched (#921)
- nginx-alpine CVEs (#881)
- CI postinstall rate limit + madge actionlint (#878, #905)

Full list in CHANGELOG.md.

## Next steps (after this PR merges)

1. Open `release/v2.13.0 → main` PR with merge-commit method
2. Tag `v2.13.0` on the merge commit
3. Cut next `release` (homelab-style bare branch) — Lucky's bare-release
migration is still pending the user removing protection on
`release/v2.11.0`
@LucasSantana-Dev LucasSantana-Dev mentioned this pull request May 21, 2026
3 tasks
LucasSantana-Dev added a commit that referenced this pull request May 21, 2026
## Release v2.13.0

Promotes \`release/v2.13.0\` to \`main\` for the v2.13.0 cut.

**$AHEAD commits across all merged PRs since v2.11.0 ship.**

(Skipping v2.12.0 — the branch existed but its work was rolled forward
into v2.13.0 alongside this session's Zod migration + CVE patches +
standards adoption.)

## Headline changes

**Added** — Guild Automation Module Executor pilot (#901), Sentry
frontend (#876), Prometheus metrics on bot+backend (#873, #875), guild
membership history (#872), Trivy image-scan Phase A (#883), landing
redesign (#868).

**Changed** — Backend migrated to Zod 4 API (#919), 3 bot circular-deps
clusters broken (#885/#886/#888).

**Fixed** — brace-expansion + ws moderate CVEs (#921), nginx-alpine CVEs
(#881), CI postinstall rate limit (#878), madge actionlint (#905).

**Internal** — shared coverageThreshold gate (#909/#914),
Feature-removal sweep checklist + dangerfile guard (#908/#913),
monitoring network, AI-doc policy, 4 new ADRs.

Full list in [CHANGELOG.md](./CHANGELOG.md).

## Merge method

This PR should land via **merge commit** (NOT squash) to preserve the
individual PR SHAs in main's history. After merge:

1. Tag \`v2.13.0\` on the merge commit
2. Create GitHub release with notes from CHANGELOG.md
3. Fast-forward \`release/v2.13.0\` to match the new main HEAD

## Test plan

- [ ] All 30 checks green except infra (snyk plan cap)
- [ ] Verify \`gh pr view 922 --json mergeCommit\` shows the chore-bump
commit on release tip
- [ ] After merge: confirm \`origin/main\` contains the full $AHEAD
commits

This branch was successfully deployed

1 active deployment
Preview — 8b9e70f6 Deployed May 16, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Pull requests that update a dependency file frontend size/xl

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant