Skip to content

Commit

Permalink
feat(spotlight): Add Sentry SDK so we can monitor (#620)
Browse files Browse the repository at this point in the history
Fixes #510.

Also allows you to debug Spotlight, with Spotlight:


![image](https://github.com/user-attachments/assets/56ca2560-1c8f-42e7-b08e-6303fd3dab6f)
  • Loading branch information
BYK authored Dec 11, 2024
1 parent 44321a8 commit f0bb9a9
Show file tree
Hide file tree
Showing 17 changed files with 1,163 additions and 342 deletions.
5 changes: 5 additions & 0 deletions .changeset/twenty-baboons-double.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@spotlightjs/spotlight': minor
---

Add Sentry SDK for monitoring
1 change: 1 addition & 0 deletions packages/overlay/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
"devDependencies": {
"@fontsource/raleway": "^5.1.0",
"@microlink/react-json-view": "^1.23.4",
"@sentry/react": "^8.43.0",
"@sentry/types": "^8.33.1",
"@sentry/utils": "^8.33.1",
"@spotlightjs/sidecar": "workspace:*",
Expand Down
10 changes: 8 additions & 2 deletions packages/overlay/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@ import { default as sentry } from './integrations/sentry/index';
import { off, on, trigger } from './lib/eventTarget';
import { activateLogger, log } from './lib/logger';
import { SpotlightContextProvider } from './lib/useSpotlightContext';
import { React, ReactDOM } from './react-instance'; // Import specific exports
import { React, ReactDOM } from './react-instance';
import type { SpotlightOverlayOptions, WindowWithSpotlight } from './types';
import { removeURLSuffix } from './utils/removeURLSuffix';
import initSentry from './utils/instrumentation';

export { default as console } from './integrations/console/index';
export { default as hydrationError } from './integrations/hydration-error/index';
Expand Down Expand Up @@ -137,7 +138,7 @@ export async function init(options: SpotlightOverlayOptions = {}) {
const finalExperiments = { ...DEFAULT_EXPERIMENTS, ...experiments };

// Sentry is enabled by default
const defaultIntegrations = () => [sentry()];
const defaultIntegrations = () => [sentry({ injectIntoSDK: !isLoadedFromSidecar })];

const context: SpotlightContext = {
open: openSpotlight,
Expand Down Expand Up @@ -185,6 +186,11 @@ export async function init(options: SpotlightOverlayOptions = {}) {
const initialTab = startFrom || (tabs.length ? `/${tabs[0].id}` : '/no-tabs');
log('Starting from', initialTab);

// TODO: Shall we enable this for other cases too such as when we use it through Django SDK?
if (isLoadedFromSidecar) {
initSentry(initialTab, { debug });
}

ReactDOM.createRoot(appRoot).render(
// <React.StrictMode>
<MemoryRouter initialEntries={[initialTab]}>
Expand Down
4 changes: 2 additions & 2 deletions packages/overlay/src/react-instance.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from 'react';
import React, { useEffect } from 'react';
import ReactDOM from 'react-dom/client';

export { React, ReactDOM };
export { React, ReactDOM, useEffect };
62 changes: 62 additions & 0 deletions packages/overlay/src/utils/instrumentation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import * as Sentry from '@sentry/react';
import { createRoutesFromChildren, matchRoutes, useLocation, useNavigationType } from 'react-router-dom';
import { useEffect } from '../react-instance';

export default function initSentry(initialTab: string, options: Sentry.BrowserOptions = {}) {
const sentryTraceParent: Record<string, string> = {};
const navTiming = performance.getEntriesByType('navigation');
if (navTiming.length > 0) {
const serverTiming = (navTiming[0] as PerformanceNavigationTiming).serverTiming;
if (serverTiming && serverTiming.length > 0) {
for (const { name, description } of serverTiming) {
if (name === 'sentryTrace' || name === 'baggage') {
sentryTraceParent[name] = description;
}
}
}
}
const hasTraceParent = Object.keys(sentryTraceParent).length === 2;
const integrations = [
// See docs for support of different versions of variation of react router
// https://docs.sentry.io/platforms/javascript/guides/react/configuration/integrations/react-router/
Sentry.reactRouterV6BrowserTracingIntegration({
instrumentPageLoad: !hasTraceParent,
useEffect,
useLocation,
useNavigationType,
createRoutesFromChildren,
matchRoutes,
}),
Sentry.replayIntegration(),
];
const hash = document.location.hash.slice(1);
if (hash.startsWith('spotlight')) {
const splitterPos = hash.indexOf('=');
const sidecarUrl = splitterPos > -1 ? decodeURIComponent(hash.slice(splitterPos + 1)) : undefined;
integrations.push(Sentry.spotlightBrowserIntegration({ sidecarUrl }));
}

const sentryClient = Sentry.init({
transport: Sentry.makeBrowserOfflineTransport(Sentry.makeFetchTransport),
dsn: 'https://51bcd92dba1128934afd1c5726c84442@o1.ingest.us.sentry.io/4508404727283713',
environment: process.env.NODE_ENV || 'development',
release: process.env.npm_package_version,

integrations,

tracesSampleRate: 1,
tracePropagationTargets: [/^\//, document.location.origin],

// Capture Replay for 1% of all sessions,
// plus for 100% of sessions with an error
// Learn more at
// https://docs.sentry.io/platforms/javascript/session-replay/configuration/#general-integration-configuration
replaysSessionSampleRate: 0.01,
replaysOnErrorSampleRate: 1.0,
...options,
});

if (hasTraceParent && sentryClient) {
Sentry.startBrowserTracingPageLoadSpan(sentryClient, { name: initialTab }, sentryTraceParent);
}
}
3 changes: 2 additions & 1 deletion packages/overlay/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ export default defineConfig({
removeReactDevToolsMessagePlugin(),
],
define: {
'process.env.NODE_ENV': "'production'",
'process.env.NODE_ENV': '"production"',
'process.env.npm_package_version': JSON.stringify(process.env.npm_package_version),
},
resolve: {
alias: {
Expand Down
1 change: 1 addition & 0 deletions packages/sidecar/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
}
},
"dependencies": {
"@sentry/node": "^8.42.0",
"kleur": "^4.1.5",
"launch-editor": "^2.9.1",
"source-map": "^0.7.4"
Expand Down
Loading

0 comments on commit f0bb9a9

Please sign in to comment.