Skip to content

Commit a2b500c

Browse files
refactor(ErrorBoundaries): Improve error monitoring and sourcemaps availability (#2854)
## Context Debugging production errors was difficult due to: - DevTools panel errors lacked router context in Sentry (only main app pathname was reported) - Sourcemaps were not fully available in production (design-system missing them) ## Description - Add dedicated DevtoolsErrorBoundary component that captures MemoryRouter pathname and tags errors with context: 'Devtools' - Add errorCategory: 'global' tag to main ErrorBoundary for better Sentry filtering - Enable sourcemap generation for design-system package - Remove filesToDeleteAfterUpload from Sentry config to keep sourcemaps available for self-hosted users <!-- Linear link --> Fixes ISSUE-1337
1 parent 2e26653 commit a2b500c

File tree

5 files changed

+65
-3
lines changed

5 files changed

+65
-3
lines changed

packages/design-system/vite.config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ export default defineConfig({
4040
fileName: 'index',
4141
formats: ['es'],
4242
},
43+
sourcemap: true,
4344
emptyOutDir: false,
4445
rollupOptions: {
4546
output: {

src/App.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { Panel, PanelGroup } from 'react-resizable-panels'
88
import { BrowserRouter, MemoryRouter } from 'react-router-dom'
99

1010
import { Spinner, ToastContainer } from '~/components/designSystem'
11+
import { DevtoolsErrorBoundary } from '~/components/developers/DevtoolsErrorBoundary'
1112
import { DEVTOOL_ROUTE } from '~/components/developers/DevtoolsRouter'
1213
import { DevtoolsView } from '~/components/developers/DevtoolsView'
1314
import { ErrorBoundary } from '~/components/ErrorBoundary'
@@ -121,7 +122,9 @@ const App = () => {
121122
</div>
122123
</Panel>
123124
<MemoryRouter initialEntries={[DEVTOOL_ROUTE]}>
124-
<DevtoolsView />
125+
<DevtoolsErrorBoundary>
126+
<DevtoolsView />
127+
</DevtoolsErrorBoundary>
125128
</MemoryRouter>
126129
</PanelGroup>
127130
</AiAgentProvider>

src/components/ErrorBoundary.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ export const ErrorBoundary = ({ children }: ErrorBoundaryProps) => {
2020
Sentry.withScope((scope) => {
2121
scope.setLevel('error')
2222
scope.setTag('errorBoundary', 'App')
23+
scope.setTag('errorCategory', 'global')
2324

2425
// Type guard for Error objects
2526
// Sentry automatically extracts error.message and error.stack for Error objects
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import { ApolloError } from '@apollo/client'
2+
import * as Sentry from '@sentry/react'
3+
import { ReactNode } from 'react'
4+
import { useLocation } from 'react-router-dom'
5+
6+
import { addToast } from '~/core/apolloClient'
7+
8+
interface DevtoolsErrorBoundaryProps {
9+
children: ReactNode
10+
}
11+
12+
export const DevtoolsErrorBoundary = ({ children }: DevtoolsErrorBoundaryProps) => {
13+
const { pathname: devtoolsPathname } = useLocation()
14+
15+
return (
16+
<Sentry.ErrorBoundary
17+
beforeCapture={(scope) => {
18+
scope.setTag('component', 'DevtoolsErrorBoundary')
19+
}}
20+
showDialog={false}
21+
onError={(error, componentStack, eventId) => {
22+
Sentry.withScope((scope) => {
23+
scope.setLevel('error')
24+
scope.setTag('errorBoundary', 'App')
25+
scope.setTag('errorCategory', 'Devtools')
26+
27+
if (error instanceof Error) {
28+
scope.setTag('errorType', error.name || 'UnknownError')
29+
} else {
30+
scope.setTag('errorType', 'UnknownError')
31+
scope.setExtra('error', String(error))
32+
}
33+
34+
scope.setExtra('componentStack', componentStack)
35+
scope.setExtra('sentryEventId', eventId)
36+
37+
// Add both router contexts for debugging
38+
if (typeof window !== 'undefined') {
39+
scope.setExtra('url', window.location.href)
40+
scope.setExtra('pathname', window.location.pathname)
41+
scope.setExtra('devtoolsPathname', devtoolsPathname)
42+
scope.setExtra('referrer', document.referrer)
43+
}
44+
45+
Sentry.captureException(error)
46+
})
47+
48+
if (!(error instanceof ApolloError)) {
49+
addToast({
50+
severity: 'danger',
51+
translateKey: 'text_622f7a3dc32ce100c46a5154',
52+
})
53+
}
54+
}}
55+
>
56+
{children}
57+
</Sentry.ErrorBoundary>
58+
)
59+
}

vite.config.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,6 @@ export default defineConfig(({ mode }) => {
8282
// Upload source maps
8383
sourcemaps: {
8484
assets: './dist/**',
85-
// Delete source maps after upload (for security)
86-
filesToDeleteAfterUpload: './dist/**/*.map',
8785
},
8886
telemetry: false,
8987
}),

0 commit comments

Comments
 (0)