(options: BrowserOptions)
| 39 | |
| 40 | /** Inits the Sentry NextJS SDK on the browser with the React SDK. */ |
| 41 | export function init(options: BrowserOptions): Client | undefined { |
| 42 | if (clientIsInitialized) { |
| 43 | consoleSandbox(() => { |
| 44 | // eslint-disable-next-line no-console |
| 45 | console.warn( |
| 46 | '[@sentry/nextjs] You are calling `Sentry.init()` more than once on the client. This can happen if you have both a `sentry.client.config.ts` and a `instrumentation-client.ts` file with `Sentry.init()` calls. It is recommended to call `Sentry.init()` once in `instrumentation-client.ts`.', |
| 47 | ); |
| 48 | }); |
| 49 | } |
| 50 | clientIsInitialized = true; |
| 51 | |
| 52 | if (!DEBUG_BUILD && options.debug) { |
| 53 | consoleSandbox(() => { |
| 54 | // eslint-disable-next-line no-console |
| 55 | console.warn( |
| 56 | '[@sentry/nextjs] You have enabled `debug: true`, but Sentry debug logging was removed from your bundle (likely via `withSentryConfig({ disableLogger: true })` / `webpack.treeshake.removeDebugLogging: true`). Set that option to `false` to see Sentry debug output.', |
| 57 | ); |
| 58 | }); |
| 59 | } |
| 60 | |
| 61 | // Remove cached trace meta tags for ISR/SSG pages before initializing |
| 62 | // This prevents the browser tracing integration from using stale trace IDs |
| 63 | if (typeof __SENTRY_TRACING__ === 'undefined' || __SENTRY_TRACING__) { |
| 64 | removeIsrSsgTraceMetaTags(); |
| 65 | } |
| 66 | |
| 67 | const opts = { |
| 68 | environment: options.environment || process.env.SENTRY_ENVIRONMENT || getVercelEnv(true) || process.env.NODE_ENV, |
| 69 | defaultIntegrations: getDefaultIntegrations(options), |
| 70 | release: process.env._sentryRelease || globalWithInjectedValues._sentryRelease, |
| 71 | ...options, |
| 72 | } satisfies BrowserOptions; |
| 73 | |
| 74 | applyTunnelRouteOption(opts); |
| 75 | applySdkMetadata(opts, 'nextjs', ['nextjs', 'react']); |
| 76 | |
| 77 | opts.ignoreSpans = [ |
| 78 | ...(opts.ignoreSpans || []), |
| 79 | // we filter out segment spans for /404 pages |
| 80 | /^\/404$/, |
| 81 | // segment spans where we didn't get a reasonable transaction name |
| 82 | // in this case, constructing a dynamic RegExp is fine because the variable is a constant |
| 83 | // we need to ensure to exact-match, so a string match isn't safe (same for /404 above) |
| 84 | new RegExp(`^${INCOMPLETE_APP_ROUTER_INSTRUMENTATION_TRANSACTION_NAME}$`), |
| 85 | ]; |
| 86 | |
| 87 | const client = reactInit(opts); |
| 88 | |
| 89 | const filterNextRedirectError: EventProcessor = (event, hint) => |
| 90 | isRedirectNavigationError(hint?.originalException) || event.exception?.values?.[0]?.value === 'NEXT_REDIRECT' |
| 91 | ? null |
| 92 | : event; |
| 93 | filterNextRedirectError.id = 'NextRedirectErrorFilter'; |
| 94 | addEventProcessor(filterNextRedirectError); |
| 95 | |
| 96 | if (process.env.NODE_ENV === 'development') { |
| 97 | addEventProcessor(devErrorSymbolicationEventProcessor); |
| 98 | } |
no test coverage detected