-
-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Expand file tree
/
Copy pathindex.ts
More file actions
149 lines (129 loc) · 6.64 KB
/
index.ts
File metadata and controls
149 lines (129 loc) · 6.64 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
// import/export got a false positive, and affects most of our index barrel files
// can be removed once following issue is fixed: https://github.com/import-js/eslint-plugin-import/issues/703
/* eslint-disable import/export */
import type { Client, EventProcessor, Integration } from '@sentry/core';
import { addEventProcessor, applySdkMetadata, consoleSandbox, getGlobalScope, GLOBAL_OBJ } from '@sentry/core';
import type { BrowserOptions } from '@sentry/react';
import { getDefaultIntegrations as getReactDefaultIntegrations, init as reactInit } from '@sentry/react';
import { DEBUG_BUILD } from '../common/debug-build';
import { devErrorSymbolicationEventProcessor } from '../common/devErrorSymbolicationEventProcessor';
import { getVercelEnv } from '../common/getVercelEnv';
import { isRedirectNavigationError } from '../common/nextNavigationErrorUtils';
import { browserTracingIntegration } from './browserTracingIntegration';
import { nextjsClientStackFrameNormalizationIntegration } from './clientNormalizationIntegration';
import { INCOMPLETE_APP_ROUTER_INSTRUMENTATION_TRANSACTION_NAME } from './routing/appRouterRoutingInstrumentation';
import { removeIsrSsgTraceMetaTags } from './routing/isrRoutingTracing';
import { applyTunnelRouteOption } from './tunnelRoute';
export * from '@sentry/react';
export * from '../common';
export { captureUnderscoreErrorException } from '../common/pages-router-instrumentation/_error';
// Override core span methods with Next.js-specific implementations that support Cache Components
export { startSpan, startSpanManual, startInactiveSpan } from '../common/utils/nextSpan';
export { browserTracingIntegration } from './browserTracingIntegration';
export { captureRouterTransitionStart } from './routing/appRouterRoutingInstrumentation';
let clientIsInitialized = false;
const globalWithInjectedValues = GLOBAL_OBJ as typeof GLOBAL_OBJ & {
_sentryRewriteFramesAssetPrefixPath: string;
_sentryAssetPrefix?: string;
_sentryBasePath?: string;
_sentryRelease?: string;
_experimentalThirdPartyOriginStackFrames?: string;
};
// Treeshakable guard to remove all code related to tracing
declare const __SENTRY_TRACING__: boolean;
/** Inits the Sentry NextJS SDK on the browser with the React SDK. */
export function init(options: BrowserOptions): Client | undefined {
if (clientIsInitialized) {
consoleSandbox(() => {
// eslint-disable-next-line no-console
console.warn(
'[@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`.',
);
});
}
clientIsInitialized = true;
if (!DEBUG_BUILD && options.debug) {
consoleSandbox(() => {
// eslint-disable-next-line no-console
console.warn(
'[@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.',
);
});
}
// Remove cached trace meta tags for ISR/SSG pages before initializing
// This prevents the browser tracing integration from using stale trace IDs
if (typeof __SENTRY_TRACING__ === 'undefined' || __SENTRY_TRACING__) {
removeIsrSsgTraceMetaTags();
}
const opts = {
environment: options.environment || process.env.SENTRY_ENVIRONMENT || getVercelEnv(true) || process.env.NODE_ENV,
defaultIntegrations: getDefaultIntegrations(options),
release: process.env._sentryRelease || globalWithInjectedValues._sentryRelease,
...options,
} satisfies BrowserOptions;
applyTunnelRouteOption(opts);
applySdkMetadata(opts, 'nextjs', ['nextjs', 'react']);
opts.ignoreSpans = [
...(opts.ignoreSpans || []),
// we filter out segment spans for /404 pages
/^\/404$/,
// segment spans where we didn't get a reasonable transaction name
// in this case, constructing a dynamic RegExp is fine because the variable is a constant
// we need to ensure to exact-match, so a string match isn't safe (same for /404 above)
new RegExp(`^${INCOMPLETE_APP_ROUTER_INSTRUMENTATION_TRANSACTION_NAME}$`),
];
const client = reactInit(opts);
const filterNextRedirectError: EventProcessor = (event, hint) =>
isRedirectNavigationError(hint?.originalException) || event.exception?.values?.[0]?.value === 'NEXT_REDIRECT'
? null
: event;
filterNextRedirectError.id = 'NextRedirectErrorFilter';
addEventProcessor(filterNextRedirectError);
if (process.env.NODE_ENV === 'development') {
addEventProcessor(devErrorSymbolicationEventProcessor);
}
try {
// @ts-expect-error `process.turbopack` is a magic string that will be replaced by Next.js
if (process.turbopack) {
getGlobalScope().setTag('turbopack', true);
}
} catch {
// Noop
// The statement above can throw because process is not defined on the client
}
return client;
}
function getDefaultIntegrations(options: BrowserOptions): Integration[] {
const customDefaultIntegrations = getReactDefaultIntegrations(options);
// This evaluates to true unless __SENTRY_TRACING__ is text-replaced with "false",
// in which case everything inside will get tree-shaken away
if (typeof __SENTRY_TRACING__ === 'undefined' || __SENTRY_TRACING__) {
customDefaultIntegrations.push(browserTracingIntegration());
}
// These values are injected at build time, based on the output directory specified in the build config. Though a default
// is set there, we set it here as well, just in case something has gone wrong with the injection.
const rewriteFramesAssetPrefixPath =
process.env._sentryRewriteFramesAssetPrefixPath ||
globalWithInjectedValues._sentryRewriteFramesAssetPrefixPath ||
'';
const assetPrefix = process.env._sentryAssetPrefix || globalWithInjectedValues._sentryAssetPrefix;
const basePath = process.env._sentryBasePath || globalWithInjectedValues._sentryBasePath;
const experimentalThirdPartyOriginStackFrames =
process.env._experimentalThirdPartyOriginStackFrames === 'true' ||
globalWithInjectedValues._experimentalThirdPartyOriginStackFrames === 'true';
customDefaultIntegrations.push(
nextjsClientStackFrameNormalizationIntegration({
assetPrefix,
basePath,
rewriteFramesAssetPrefixPath,
experimentalThirdPartyOriginStackFrames,
}),
);
return customDefaultIntegrations;
}
/**
* Just a passthrough in case this is imported from the client.
*/
export function withSentryConfig<T>(exportedUserNextConfig: T): T {
return exportedUserNextConfig;
}