From 73f407455eb4202b9487665c03e59cf972783859 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Thu, 5 Oct 2023 16:33:59 -0500 Subject: [PATCH] Sentry: use DSN from SoapboxConfig --- src/containers/soapbox.tsx | 5 +- src/hooks/index.ts | 3 +- src/hooks/useSentry.ts | 50 ++++++++++++++++++++ src/main.tsx | 4 -- src/monitoring.ts | 56 ++++------------------- src/normalizers/soapbox/soapbox-config.ts | 1 + src/sentry.ts | 13 ++++++ 7 files changed, 80 insertions(+), 52 deletions(-) create mode 100644 src/hooks/useSentry.ts create mode 100644 src/sentry.ts diff --git a/src/containers/soapbox.tsx b/src/containers/soapbox.tsx index 253189714..9df5b7a19 100644 --- a/src/containers/soapbox.tsx +++ b/src/containers/soapbox.tsx @@ -28,8 +28,9 @@ import { useAppSelector, useAppDispatch, useOwnAccount, - useSoapboxConfig, + useSentry, useSettings, + useSoapboxConfig, useTheme, useLocale, } from 'soapbox/hooks'; @@ -224,6 +225,8 @@ const SoapboxHead: React.FC = ({ children }) => { 'demetricator': settings.get('demetricator'), }); + useSentry(soapboxConfig.sentryDsn); + return ( <> diff --git a/src/hooks/index.ts b/src/hooks/index.ts index 98d600547..ef77478df 100644 --- a/src/hooks/index.ts +++ b/src/hooks/index.ts @@ -19,7 +19,8 @@ export { useOwnAccount } from './useOwnAccount'; export { usePrevious } from './usePrevious'; export { useRefEventHandler } from './useRefEventHandler'; export { useRegistrationStatus } from './useRegistrationStatus'; +export { useSentry } from './useSentry'; export { useSettings } from './useSettings'; export { useSoapboxConfig } from './useSoapboxConfig'; export { useSystemTheme } from './useSystemTheme'; -export { useTheme } from './useTheme'; +export { useTheme } from './useTheme'; \ No newline at end of file diff --git a/src/hooks/useSentry.ts b/src/hooks/useSentry.ts new file mode 100644 index 000000000..2a13b2645 --- /dev/null +++ b/src/hooks/useSentry.ts @@ -0,0 +1,50 @@ +import { useEffect } from 'react'; + +/** Hook to start Sentry. Should only be called once. */ +function useSentry(dsn: string | undefined) { + useEffect(() => { + if (dsn) { + startSentry(dsn).catch(console.error); + } + }, [dsn]); +} + +/** Start Sentry. */ +async function startSentry(dsn: string): Promise { + const [Sentry, { Integrations: Integrations }] = await Promise.all([ + import('@sentry/react'), + import('@sentry/tracing'), + ]); + + Sentry.init({ + dsn, + debug: false, + integrations: [new Integrations.BrowserTracing()], + + // Filter events. + // https://docs.sentry.io/platforms/javascript/configuration/filtering/ + ignoreErrors: [ + // Network errors. + 'AxiosError', + // sw.js couldn't be downloaded. + 'Failed to update a ServiceWorker for scope', + // Useful for try/catch, useless as a Sentry error. + 'AbortError', + // localForage error in FireFox private browsing mode (which doesn't support IndexedDB). + // We only use IndexedDB as a cache, so we can safely ignore the error. + 'No available storage method found', + ], + denyUrls: [ + // Browser extensions. + /extensions\//i, + /^chrome:\/\//i, + /^moz-extension:\/\//i, + ], + + // We recommend adjusting this value in production, or using tracesSampler + // for finer control + tracesSampleRate: 1.0, + }); +} + +export { useSentry }; \ No newline at end of file diff --git a/src/main.tsx b/src/main.tsx index 74d967b01..33b325dab 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -23,13 +23,9 @@ import './styles/tailwind.css'; import './precheck'; import { default as Soapbox } from './containers/soapbox'; -import * as monitoring from './monitoring'; import ready from './ready'; import { registerSW } from './utils/sw'; -// Sentry -monitoring.start(); - if (BuildConfig.NODE_ENV === 'production') { printConsoleWarning(); registerSW('/sw.js'); diff --git a/src/monitoring.ts b/src/monitoring.ts index ab0d390dc..128b3a5ba 100644 --- a/src/monitoring.ts +++ b/src/monitoring.ts @@ -1,49 +1,13 @@ -import * as BuildConfig from 'soapbox/build-config'; - import type { CaptureContext } from '@sentry/types'; -export const start = (): void => { - Promise.all([ - import('@sentry/react'), - import('@sentry/tracing'), - ]).then(([Sentry, { Integrations: Integrations }]) => { - Sentry.init({ - dsn: BuildConfig.SENTRY_DSN, - environment: BuildConfig.NODE_ENV, - debug: false, - integrations: [new Integrations.BrowserTracing()], +/** Capture the exception and report it to Sentry. */ +async function captureException (exception: any, captureContext?: CaptureContext | undefined): Promise { + try { + const Sentry = await import('@sentry/react'); + Sentry.captureException(exception, captureContext); + } catch (e) { + console.error(e); + } +} - // Filter events. - // https://docs.sentry.io/platforms/javascript/configuration/filtering/ - ignoreErrors: [ - // Network errors. - 'AxiosError', - // sw.js couldn't be downloaded. - 'Failed to update a ServiceWorker for scope', - // Useful for try/catch, useless as a Sentry error. - 'AbortError', - // localForage error in FireFox private browsing mode (which doesn't support IndexedDB). - // We only use IndexedDB as a cache, so we can safely ignore the error. - 'No available storage method found', - ], - denyUrls: [ - // Browser extensions. - /extensions\//i, - /^chrome:\/\//i, - /^moz-extension:\/\//i, - ], - - // We recommend adjusting this value in production, or using tracesSampler - // for finer control - tracesSampleRate: 1.0, - }); - }).catch(console.error); -}; - -export const captureException = (exception: any, captureContext?: CaptureContext | undefined): void => { - import('@sentry/react') - .then(Sentry => { - Sentry.captureException(exception, captureContext); - }) - .catch(console.error); -}; +export { captureException }; diff --git a/src/normalizers/soapbox/soapbox-config.ts b/src/normalizers/soapbox/soapbox-config.ts index 403c92a32..4092f8367 100644 --- a/src/normalizers/soapbox/soapbox-config.ts +++ b/src/normalizers/soapbox/soapbox-config.ts @@ -116,6 +116,7 @@ export const SoapboxConfigRecord = ImmutableRecord({ * On some platforms this can be too blurry without additional configuration. */ mediaPreview: false, + sentryDsn: undefined as string | undefined, }, 'SoapboxConfig'); type SoapboxConfigMap = ImmutableMap; diff --git a/src/sentry.ts b/src/sentry.ts new file mode 100644 index 000000000..ac454501a --- /dev/null +++ b/src/sentry.ts @@ -0,0 +1,13 @@ +import type { CaptureContext } from '@sentry/types'; + +/** Capture the exception in Sentry. */ +async function captureException (exception: any, captureContext?: CaptureContext | undefined): Promise { + try { + const Sentry = await import('@sentry/react'); + Sentry.captureException(exception, captureContext); + } catch (e) { + console.error(e); + } +} + +export { startSentry, captureException }; \ No newline at end of file