feat: Sentry error monitoring for React frontend (#98)
* feat: add Sentry error monitoring, tracing, and session replay - Install @sentry/react and @sentry/vite-plugin - Create instrument.ts with error monitoring, browser tracing (20% prod), and session replay (10% sessions, 100% on errors) - Wire React 19 reactErrorHandler() on createRoot error hooks - Wrap router with wrapCreateBrowserRouterV7 for route-aware transactions - Configure sentryVitePlugin for source map uploads - Add VITE_SENTRY_DSN to .env.example Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: add Sentry error monitoring and tracing to FastAPI backend - Install sentry-sdk[fastapi] with auto-enabled FastAPI + Anthropic integrations - Init before app = FastAPI() with env-aware sample rates (100% dev, 20% prod) - Filter /health endpoint from traces to reduce noise - Add SENTRY_DSN to config settings Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit was merged in pull request #98.
This commit is contained in:
25
frontend/src/instrument.ts
Normal file
25
frontend/src/instrument.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import * as Sentry from "@sentry/react";
|
||||
|
||||
Sentry.init({
|
||||
dsn: import.meta.env.VITE_SENTRY_DSN,
|
||||
environment: import.meta.env.MODE,
|
||||
|
||||
integrations: [
|
||||
Sentry.browserTracingIntegration(),
|
||||
Sentry.replayIntegration({
|
||||
maskAllText: false,
|
||||
blockAllMedia: false,
|
||||
}),
|
||||
],
|
||||
|
||||
// Tracing — capture 100% in dev, 20% in production
|
||||
tracesSampleRate: import.meta.env.PROD ? 0.2 : 1.0,
|
||||
tracePropagationTargets: [
|
||||
"localhost",
|
||||
/^https:\/\/api\.resolutionflow\.com/,
|
||||
],
|
||||
|
||||
// Session Replay — record 10% of sessions, 100% of error sessions
|
||||
replaysSessionSampleRate: 0.1,
|
||||
replaysOnErrorSampleRate: 1.0,
|
||||
});
|
||||
@@ -1,11 +1,18 @@
|
||||
import "./instrument"; // Sentry must init before any other imports
|
||||
|
||||
import { StrictMode } from 'react'
|
||||
import { createRoot } from 'react-dom/client'
|
||||
import { reactErrorHandler } from '@sentry/react'
|
||||
import { HelmetProvider } from 'react-helmet-async'
|
||||
import { Toaster } from 'sonner'
|
||||
import './index.css'
|
||||
import App from './App'
|
||||
|
||||
createRoot(document.getElementById('root')!).render(
|
||||
createRoot(document.getElementById('root')!, {
|
||||
onUncaughtError: reactErrorHandler(),
|
||||
onCaughtError: reactErrorHandler(),
|
||||
onRecoverableError: reactErrorHandler(),
|
||||
}).render(
|
||||
<StrictMode>
|
||||
<HelmetProvider>
|
||||
{/* Toast notification system - theme syncs automatically via CSS custom properties */}
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
import { createBrowserRouter } from 'react-router-dom'
|
||||
import * as Sentry from '@sentry/react'
|
||||
import { lazy, Suspense } from 'react'
|
||||
import { AppLayout, ProtectedRoute } from '@/components/layout'
|
||||
import { RouteError } from '@/components/common/RouteError'
|
||||
import { ErrorBoundary } from '@/components/common/ErrorBoundary'
|
||||
import { PageLoader } from '@/components/common/PageLoader'
|
||||
|
||||
const sentryCreateBrowserRouter = Sentry.wrapCreateBrowserRouterV7(createBrowserRouter)
|
||||
import {
|
||||
LoginPage,
|
||||
RegisterPage,
|
||||
@@ -73,7 +76,7 @@ function page(Component: React.LazyExoticComponent<React.ComponentType>) {
|
||||
)
|
||||
}
|
||||
|
||||
export const router = createBrowserRouter([
|
||||
export const router = sentryCreateBrowserRouter([
|
||||
{
|
||||
path: '/login',
|
||||
element: <LoginPage />,
|
||||
|
||||
Reference in New Issue
Block a user