feat(desktop): add Sentry error tracking to desktop app#484
feat(desktop): add Sentry error tracking to desktop app#484saddlepaddle merged 5 commits intomainfrom
Conversation
|
Warning Rate limit exceeded@saddlepaddle has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 10 minutes and 49 seconds before requesting another review. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. 📒 Files selected for processing (2)
WalkthroughThis PR integrates Sentry error tracking into the Electron desktop application by adding the Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant MainProc as Main Process
participant Renderer as Renderer Process
participant AppState as App Bootstrap
participant Sentry as Sentry Service
rect rgb(200, 220, 255)
Note over MainProc,Sentry: Main Process Startup
AppState->>MainProc: Start app
MainProc->>MainProc: initSentry() called
MainProc->>MainProc: Check singleton flag
MainProc->>MainProc: Validate SENTRY_DSN_DESKTOP
MainProc->>Sentry: Dynamic import `@sentry/electron/main`
MainProc->>Sentry: Sentry.init(config)
Sentry-->>MainProc: Initialized
MainProc->>MainProc: Set initialized flag
end
rect rgb(200, 255, 220)
Note over Renderer,Sentry: Renderer Process Startup
AppState->>Renderer: Load renderer
Renderer->>Renderer: initSentry() called
Renderer->>Renderer: Check singleton flag
Renderer->>Renderer: Validate SENTRY_DSN_DESKTOP
Renderer->>Sentry: Dynamic import `@sentry/electron/renderer`
Renderer->>Sentry: Sentry.init(config)
Sentry-->>Renderer: Initialized
Renderer->>Renderer: Set initialized flag
end
rect rgb(255, 235, 200)
Note over MainProc,Sentry: Error Capture Flow (Example)
MainProc->>MainProc: TRPC procedure executes
MainProc->>MainProc: Error thrown
MainProc->>MainProc: sentryMiddleware catches error
MainProc->>Sentry: Sentry.captureException(error, context)
Sentry-->>MainProc: Error captured
MainProc-->>Renderer: Error response
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~22 minutes Possibly related PRs
Pre-merge checks and finishing touches❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 passed)
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. Comment |
- Add Sentry integration for main and renderer processes - Use dynamic imports to avoid electron-vite bundler issues - Add tRPC middleware to automatically capture all backend errors - Update CSP to allow sentry-ipc: protocol and *.sentry.io - Add SENTRY_DSN_DESKTOP to env schema and release workflow 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
416e30f to
7800394
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (3)
apps/desktop/src/main/lib/sentry.ts (1)
19-19: Consider lowering development trace sample rate.A
tracesSampleRateof1.0(100%) in development could generate excessive trace data and impact performance during dev work with many errors or transactions. Consider lowering it to0.3or0.5for development to balance observability with performance.🔎 Suggested adjustment
- tracesSampleRate: env.NODE_ENV === "development" ? 1.0 : 0.1, + tracesSampleRate: env.NODE_ENV === "development" ? 0.3 : 0.1,apps/desktop/src/lib/trpc/routers/settings/index.ts (1)
169-171: Consider restricting test error endpoint to development.The
triggerTestErrormutation is useful for testing, but it should be restricted to development environments to prevent misuse in production builds.🔎 Suggested guard
triggerTestError: publicProcedure.mutation(() => { + if (env.NODE_ENV !== "development") { + throw new Error("Test endpoints are only available in development"); + } throw new Error("Test error from main process (Sentry test)"); }),Note: You'll need to import
envfrom"main/env.main"at the top of the file.apps/desktop/src/main/index.ts (1)
1-3: Consider awaiting Sentry initialization.The
initSentry()call is async but not awaited, which means the app continues startup without confirming Sentry is ready. This could result in early errors not being captured if they occur before initialization completes.🔎 Options to consider
Option 1: Await initialization (recommended if startup blocking is acceptable)
-initSentry(); +await initSentry(); import path from "node:path";This requires wrapping in an async context or moving the import section. Since the rest of the startup is already async (see line 127), you could restructure like:
-import { initSentry } from "./lib/sentry"; - -initSentry(); - import path from "node:path"; import { app, BrowserWindow } from "electron"; +import { initSentry } from "./lib/sentry"; // ... other imports // ... rest of code ... (async () => { + await initSentry(); await app.whenReady();Option 2: Fire-and-forget with explicit comment (if non-blocking is preferred)
-initSentry(); +// Initialize Sentry (async, non-blocking to avoid delaying app startup) +initSentry().catch(err => console.error('[main] Sentry init failed:', err));The current approach may miss errors that occur very early in the startup sequence, but this is often an acceptable tradeoff to avoid blocking app launch.
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
bun.lockis excluded by!**/*.lock
📒 Files selected for processing (13)
.github/workflows/release-desktop.ymlapps/desktop/electron.vite.config.tsapps/desktop/package.jsonapps/desktop/src/lib/trpc/index.tsapps/desktop/src/lib/trpc/routers/settings/index.tsapps/desktop/src/main/env.main.tsapps/desktop/src/main/index.tsapps/desktop/src/main/lib/sentry.tsapps/desktop/src/renderer/env.renderer.tsapps/desktop/src/renderer/index.htmlapps/desktop/src/renderer/index.tsxapps/desktop/src/renderer/lib/sentry.tsapps/desktop/src/renderer/screens/main/components/SettingsView/AccountSettings/AccountSettings.tsx
🧰 Additional context used
📓 Path-based instructions (11)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Avoid using any type in TypeScript - maintain type safety unless absolutely necessary
Files:
apps/desktop/src/main/index.tsapps/desktop/src/lib/trpc/routers/settings/index.tsapps/desktop/src/renderer/lib/sentry.tsapps/desktop/src/main/lib/sentry.tsapps/desktop/src/main/env.main.tsapps/desktop/src/renderer/index.tsxapps/desktop/src/lib/trpc/index.tsapps/desktop/electron.vite.config.tsapps/desktop/src/renderer/env.renderer.tsapps/desktop/src/renderer/screens/main/components/SettingsView/AccountSettings/AccountSettings.tsx
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
Run Biome for formatting, linting, import organization, and safe fixes at the root level using bun run lint:fix
Files:
apps/desktop/src/main/index.tsapps/desktop/src/lib/trpc/routers/settings/index.tsapps/desktop/src/renderer/lib/sentry.tsapps/desktop/src/main/lib/sentry.tsapps/desktop/src/main/env.main.tsapps/desktop/src/renderer/index.tsxapps/desktop/src/lib/trpc/index.tsapps/desktop/electron.vite.config.tsapps/desktop/src/renderer/env.renderer.tsapps/desktop/src/renderer/screens/main/components/SettingsView/AccountSettings/AccountSettings.tsx
apps/desktop/src/{main,renderer,preload}/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use type-safe IPC communication - define channel types in apps/desktop/src/shared/ipc-channels.ts before implementing handlers
Files:
apps/desktop/src/main/index.tsapps/desktop/src/renderer/lib/sentry.tsapps/desktop/src/main/lib/sentry.tsapps/desktop/src/main/env.main.tsapps/desktop/src/renderer/index.tsxapps/desktop/src/renderer/env.renderer.tsapps/desktop/src/renderer/screens/main/components/SettingsView/AccountSettings/AccountSettings.tsx
apps/desktop/src/main/**/*.ts
📄 CodeRabbit inference engine (AGENTS.md)
Accept object parameters in IPC handlers - do not use positional parameters in ipcMain.handle()
Files:
apps/desktop/src/main/index.tsapps/desktop/src/main/lib/sentry.tsapps/desktop/src/main/env.main.ts
apps/desktop/src/main/index.ts
📄 CodeRabbit inference engine (AGENTS.md)
Load environment variables in src/main/index.ts and electron.vite.config.ts with override: true before other imports
Files:
apps/desktop/src/main/index.ts
apps/desktop/**/*.{ts,tsx}
📄 CodeRabbit inference engine (apps/desktop/AGENTS.md)
apps/desktop/**/*.{ts,tsx}: For Electron interprocess communication, ALWAYS use tRPC as defined insrc/lib/trpc
Use alias as defined intsconfig.jsonwhen possible
Prefer zustand for state management if it makes sense. Do not use effect unless absolutely necessary.
For tRPC subscriptions with trpc-electron, ALWAYS use the observable pattern from@trpc/server/observableinstead of async generators, as the library explicitly checksisObservable(result)and throws an error otherwise
Files:
apps/desktop/src/main/index.tsapps/desktop/src/lib/trpc/routers/settings/index.tsapps/desktop/src/renderer/lib/sentry.tsapps/desktop/src/main/lib/sentry.tsapps/desktop/src/main/env.main.tsapps/desktop/src/renderer/index.tsxapps/desktop/src/lib/trpc/index.tsapps/desktop/electron.vite.config.tsapps/desktop/src/renderer/env.renderer.tsapps/desktop/src/renderer/screens/main/components/SettingsView/AccountSettings/AccountSettings.tsx
apps/desktop/src/renderer/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Never import Node.js modules in renderer process or shared code - use only in main process (src/main/)
Files:
apps/desktop/src/renderer/lib/sentry.tsapps/desktop/src/renderer/index.tsxapps/desktop/src/renderer/env.renderer.tsapps/desktop/src/renderer/screens/main/components/SettingsView/AccountSettings/AccountSettings.tsx
**/*.{tsx,css}
📄 CodeRabbit inference engine (AGENTS.md)
Use React + TailwindCSS v4 + shadcn/ui for UI development
Files:
apps/desktop/src/renderer/index.tsxapps/desktop/src/renderer/screens/main/components/SettingsView/AccountSettings/AccountSettings.tsx
**/{components,features}/**/[!.]*.tsx
📄 CodeRabbit inference engine (AGENTS.md)
Organize project structure with one folder per component: ComponentName/ComponentName.tsx with index.ts barrel export
Files:
apps/desktop/src/renderer/screens/main/components/SettingsView/AccountSettings/AccountSettings.tsx
**/{components,features}/**/*.{ts,tsx,test.ts,test.tsx,stories.tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Co-locate component dependencies (utils, hooks, constants, config, tests, stories) next to the file using them
Files:
apps/desktop/src/renderer/screens/main/components/SettingsView/AccountSettings/AccountSettings.tsx
**/{components,features}/**/*.tsx
📄 CodeRabbit inference engine (AGENTS.md)
**/{components,features}/**/*.tsx: Nest components in parent's components/ folder if used only once, promote to highest shared parent's components/ if used 2+ times
Use one component per file - do not combine multiple components in a single file
Files:
apps/desktop/src/renderer/screens/main/components/SettingsView/AccountSettings/AccountSettings.tsx
🧠 Learnings (8)
📓 Common learnings
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: apps/desktop/AGENTS.md:0-0
Timestamp: 2025-12-21T04:39:28.543Z
Learning: Applies to apps/desktop/**/*.{ts,tsx} : For Electron interprocess communication, ALWAYS use tRPC as defined in `src/lib/trpc`
📚 Learning: 2025-12-18T23:19:10.415Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-18T23:19:10.415Z
Learning: Applies to apps/desktop/src/main/index.ts : Load environment variables in src/main/index.ts and electron.vite.config.ts with override: true before other imports
Applied to files:
.github/workflows/release-desktop.ymlapps/desktop/src/main/index.tsapps/desktop/src/main/lib/sentry.tsapps/desktop/src/main/env.main.tsapps/desktop/src/renderer/index.tsxapps/desktop/electron.vite.config.tsapps/desktop/src/renderer/env.renderer.ts
📚 Learning: 2025-12-18T23:19:10.415Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-18T23:19:10.415Z
Learning: Applies to apps/desktop/src/renderer/**/*.{ts,tsx} : Never import Node.js modules in renderer process or shared code - use only in main process (src/main/)
Applied to files:
apps/desktop/src/renderer/lib/sentry.tsapps/desktop/src/main/lib/sentry.tsapps/desktop/src/renderer/index.tsxapps/desktop/electron.vite.config.tsapps/desktop/src/renderer/screens/main/components/SettingsView/AccountSettings/AccountSettings.tsx
📚 Learning: 2025-12-18T23:19:10.415Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-18T23:19:10.415Z
Learning: Applies to apps/desktop/src/{main,renderer,preload}/**/*.{ts,tsx} : Use type-safe IPC communication - define channel types in apps/desktop/src/shared/ipc-channels.ts before implementing handlers
Applied to files:
apps/desktop/src/renderer/lib/sentry.tsapps/desktop/src/renderer/index.tsxapps/desktop/src/renderer/index.htmlapps/desktop/src/lib/trpc/index.tsapps/desktop/electron.vite.config.ts
📚 Learning: 2025-12-21T04:39:28.543Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: apps/desktop/AGENTS.md:0-0
Timestamp: 2025-12-21T04:39:28.543Z
Learning: Applies to apps/desktop/**/*.{ts,tsx} : For Electron interprocess communication, ALWAYS use tRPC as defined in `src/lib/trpc`
Applied to files:
apps/desktop/src/lib/trpc/index.ts
📚 Learning: 2025-12-21T04:39:28.543Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: apps/desktop/AGENTS.md:0-0
Timestamp: 2025-12-21T04:39:28.543Z
Learning: Applies to apps/desktop/**/*.{ts,tsx} : For tRPC subscriptions with trpc-electron, ALWAYS use the observable pattern from `trpc/server/observable` instead of async generators, as the library explicitly checks `isObservable(result)` and throws an error otherwise
Applied to files:
apps/desktop/src/lib/trpc/index.ts
📚 Learning: 2025-12-18T23:19:10.415Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-18T23:19:10.415Z
Learning: Applies to apps/desktop/src/main/**/*.ts : Accept object parameters in IPC handlers - do not use positional parameters in ipcMain.handle()
Applied to files:
apps/desktop/src/lib/trpc/index.ts
📚 Learning: 2025-12-18T23:19:10.415Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-18T23:19:10.415Z
Learning: Applies to apps/*/app/**/proxy.ts : Never create middleware.ts in Next.js 16 - always use proxy.ts for request interception
Applied to files:
apps/desktop/src/lib/trpc/index.ts
🧬 Code graph analysis (3)
apps/desktop/src/main/index.ts (2)
apps/desktop/src/main/lib/sentry.ts (1)
initSentry(5-28)apps/desktop/src/renderer/lib/sentry.ts (1)
initSentry(5-29)
apps/desktop/src/main/lib/sentry.ts (3)
apps/desktop/src/renderer/lib/sentry.ts (1)
initSentry(5-29)apps/desktop/src/main/env.main.ts (1)
env(12-44)apps/desktop/src/renderer/env.renderer.ts (1)
env(45-47)
apps/desktop/src/renderer/index.tsx (2)
apps/desktop/src/main/lib/sentry.ts (1)
initSentry(5-28)apps/desktop/src/renderer/lib/sentry.ts (1)
initSentry(5-29)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
- GitHub Check: Deploy Web
- GitHub Check: Deploy Marketing
- GitHub Check: Deploy API
- GitHub Check: Deploy Admin
- GitHub Check: Deploy Docs
- GitHub Check: Build
🔇 Additional comments (15)
apps/desktop/src/renderer/index.html (1)
14-18: LGTM - CSP correctly updated for Sentry.The Content Security Policy changes properly allow Sentry error reporting via both HTTPS (for cloud reporting) and the
sentry-ipc:protocol (for Electron IPC communication). The inline documentation is also helpful.apps/desktop/src/renderer/env.renderer.ts (1)
22-22: LGTM - Environment variable properly added.The
SENTRY_DSN_DESKTOPenvironment variable follows the established pattern for optional configuration in the renderer process, with proper Zod v4 validation and build-time injection viaimport.meta.env.Also applies to: 42-42
apps/desktop/src/main/lib/sentry.ts (1)
5-27: LGTM - Sentry initialization follows best practices.The implementation correctly:
- Uses dynamic imports to avoid bundler issues
- Prevents double-initialization with a guard flag
- Disables PII transmission for privacy (
sendDefaultPii: false)- Includes appropriate error handling
apps/desktop/src/main/env.main.ts (1)
23-23: LGTM - Environment variable properly configured.The
SENTRY_DSN_DESKTOPaddition follows the established pattern for optional server-side environment variables, with proper Zod v4 validation and runtime mapping fromprocess.env.Also applies to: 37-37
.github/workflows/release-desktop.yml (1)
65-65: LGTM - Secret properly exposed to build process.The
SENTRY_DSN_DESKTOPsecret is correctly passed to the compile step where Vite will inject it into the bundle. This follows the same pattern as other secrets in the workflow.apps/desktop/package.json (1)
40-40: @sentry/electron 7.5.0 is acceptable and no security updates are required.The version 7.5.0 is documented as the latest version by Sentry's official documentation, and no known security vulnerabilities were identified for this package. The caret notation (^7.5.0) in package.json allows for safe minor and patch updates within the 7.x release line.
apps/desktop/src/renderer/index.tsx (1)
1-4: LGTM! Early Sentry initialization with fire-and-forget pattern.The async
initSentry()is intentionally called withoutawaitto avoid blocking app bootstrap. This is acceptable since the function handles its own errors internally and Sentry initialization is not critical for app functionality. The early placement before React imports ensures error tracking is available as soon as possible.apps/desktop/src/renderer/screens/main/components/SettingsView/AccountSettings/AccountSettings.tsx (1)
85-102: LGTM! Well-structured development-only testing UI.The developer section is properly gated behind
env.NODE_ENV === "development"and provides clear testing controls for both renderer and main process error reporting.apps/desktop/src/lib/trpc/index.ts (2)
18-45: LGTM! Error capture middleware with appropriate safeguards.The middleware correctly:
- Uses dynamic import to avoid bundler issues
- Captures the original error when wrapped in TRPCError
- Adds useful context via tags (path, type, code)
- Silently handles Sentry unavailability
Since tRPC procedures execute in the main process via
trpc-electron, the@sentry/electron/mainimport is appropriate here.
47-49: Good centralized error reporting pattern.Applying
sentryMiddlewaretopublicProcedureensures all tRPC procedures automatically get Sentry error capture without requiring individual instrumentation.apps/desktop/src/renderer/lib/sentry.ts (2)
5-29: Clean async initialization with proper guards.The implementation correctly:
- Uses a singleton flag to prevent re-initialization
- Gracefully handles missing DSN configuration
- Uses dynamic import to avoid bundler issues
- Logs success/failure for debugging
16-22: AddreplayIntegration()to the integrations array for explicit session replay configuration.The sample rates
replaysSessionSampleRateandreplaysOnErrorSampleRatewill function without explicit integration, but Sentry's documented approach includesSentry.replayIntegration()in the integrations array for proper configuration and future compatibility.apps/desktop/electron.vite.config.ts (3)
91-93: LGTM! Consistent with existing env var pattern.The
SENTRY_DSN_DESKTOPis properly exposed to the main process using the same pattern as other environment variables likeGOOGLE_CLIENT_ID.
105-110: Correct externalization of Sentry package.Adding
@sentry/electronto externals is necessary since it includes native bindings that cannot be bundled by Vite/Rollup.
168-170: LGTM! Renderer env var exposure.The
SENTRY_DSN_DESKTOPis correctly exposed viaimport.meta.envfor the renderer process, matching the pattern used for PostHog configuration.
Remove test buttons and procedures that were used for verifying Sentry integration. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Sentry uses IPC to communicate with main process and imports node-core modules that can't be bundled for browser. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Summary
sentry-ipc:protocol and*.sentry.iofor error reportingSENTRY_DSN_DESKTOPto env schema and release workflowTest plan
bun run devin desktop app🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Chores
✏️ Tip: You can customize this high-level summary in your review settings.