1
1
import { hasTracingEnabled } from '@sentry/core' ;
2
- import { RewriteFrames } from '@sentry/integrations' ;
3
2
import type { BrowserOptions } from '@sentry/react' ;
4
3
import {
5
- BrowserTracing ,
6
- Integrations ,
7
- defaultRequestInstrumentationOptions ,
4
+ Integrations as OriginalIntegrations ,
8
5
getCurrentScope ,
6
+ getDefaultIntegrations as getReactDefaultIntegrations ,
9
7
init as reactInit ,
10
8
} from '@sentry/react' ;
11
- import type { EventProcessor } from '@sentry/types' ;
12
- import { addOrUpdateIntegration } from '@sentry/utils' ;
9
+ import type { EventProcessor , Integration } from '@sentry/types' ;
13
10
14
11
import { devErrorSymbolicationEventProcessor } from '../common/devErrorSymbolicationEventProcessor' ;
15
12
import { getVercelEnv } from '../common/getVercelEnv' ;
16
13
import { buildMetadata } from '../common/metadata' ;
17
- import { nextRouterInstrumentation } from './routing/nextRoutingInstrumentation' ;
14
+ import { BrowserTracing } from './browserTracingIntegration' ;
15
+ import { rewriteFramesIntegration } from './rewriteFramesIntegration' ;
18
16
import { applyTunnelRouteOption } from './tunnelRoute' ;
19
17
20
18
export * from '@sentry/react' ;
21
19
export { nextRouterInstrumentation } from './routing/nextRoutingInstrumentation' ;
22
20
export { captureUnderscoreErrorException } from '../common/_error' ;
23
21
24
- export { Integrations } ;
22
+ export const Integrations = {
23
+ ...OriginalIntegrations ,
24
+ BrowserTracing,
25
+ } ;
25
26
26
27
// Previously we expected users to import `BrowserTracing` like this:
27
28
//
@@ -33,27 +34,24 @@ export { Integrations };
33
34
//
34
35
// import { BrowserTracing } from '@sentry/nextjs';
35
36
// const instance = new BrowserTracing();
36
- export { BrowserTracing } ;
37
+ export { BrowserTracing , rewriteFramesIntegration } ;
37
38
38
39
// Treeshakable guard to remove all code related to tracing
39
40
declare const __SENTRY_TRACING__ : boolean ;
40
41
41
- const globalWithInjectedValues = global as typeof global & {
42
- __rewriteFramesAssetPrefixPath__ : string ;
43
- } ;
44
-
45
42
/** Inits the Sentry NextJS SDK on the browser with the React SDK. */
46
43
export function init ( options : BrowserOptions ) : void {
47
44
const opts = {
48
45
environment : getVercelEnv ( true ) || process . env . NODE_ENV ,
46
+ defaultIntegrations : getDefaultIntegrations ( options ) ,
49
47
...options ,
50
48
} ;
51
49
50
+ fixBrowserTracingIntegration ( opts ) ;
51
+
52
52
applyTunnelRouteOption ( opts ) ;
53
53
buildMetadata ( opts , [ 'nextjs' , 'react' ] ) ;
54
54
55
- addClientIntegrations ( opts ) ;
56
-
57
55
reactInit ( opts ) ;
58
56
59
57
const scope = getCurrentScope ( ) ;
@@ -68,72 +66,53 @@ export function init(options: BrowserOptions): void {
68
66
}
69
67
}
70
68
71
- function addClientIntegrations ( options : BrowserOptions ) : void {
72
- let integrations = options . integrations || [ ] ;
73
-
74
- // This value is injected at build time, based on the output directory specified in the build config. Though a default
75
- // is set there, we set it here as well, just in case something has gone wrong with the injection.
76
- const assetPrefixPath = globalWithInjectedValues . __rewriteFramesAssetPrefixPath__ || '' ;
77
-
78
- // eslint-disable-next-line deprecation/deprecation
79
- const defaultRewriteFramesIntegration = new RewriteFrames ( {
80
- // Turn `<origin>/<path>/_next/static/...` into `app:///_next/static/...`
81
- iteratee : frame => {
82
- try {
83
- const { origin } = new URL ( frame . filename as string ) ;
84
- frame . filename = frame . filename ?. replace ( origin , 'app://' ) . replace ( assetPrefixPath , '' ) ;
85
- } catch ( err ) {
86
- // Filename wasn't a properly formed URL, so there's nothing we can do
87
- }
88
-
89
- // We need to URI-decode the filename because Next.js has wildcard routes like "/users/[id].js" which show up as "/users/%5id%5.js" in Error stacktraces.
90
- // The corresponding sources that Next.js generates have proper brackets so we also need proper brackets in the frame so that source map resolving works.
91
- if ( frame . filename && frame . filename . startsWith ( 'app:///_next' ) ) {
92
- frame . filename = decodeURI ( frame . filename ) ;
93
- }
94
-
95
- if (
96
- frame . filename &&
97
- frame . filename . match (
98
- / ^ a p p : \/ \/ \/ _ n e x t \/ s t a t i c \/ c h u n k s \/ ( m a i n - | m a i n - a p p - | p o l y f i l l s - | w e b p a c k - | f r a m e w o r k - | f r a m e w o r k \. ) [ 0 - 9 a - f ] + \. j s $ / ,
99
- )
100
- ) {
101
- // We don't care about these frames. It's Next.js internal code.
102
- frame . in_app = false ;
103
- }
104
-
105
- return frame ;
106
- } ,
107
- } ) ;
108
- integrations = addOrUpdateIntegration ( defaultRewriteFramesIntegration , integrations ) ;
69
+ // TODO v8: Remove this again
70
+ // We need to handle BrowserTracing passed to `integrations` that comes from `@sentry/tracing`, not `@sentry/sveltekit` :(
71
+ function fixBrowserTracingIntegration ( options : BrowserOptions ) : void {
72
+ const { integrations } = options ;
73
+ if ( ! integrations ) {
74
+ return ;
75
+ }
76
+
77
+ if ( Array . isArray ( integrations ) ) {
78
+ options . integrations = maybeUpdateBrowserTracingIntegration ( integrations ) ;
79
+ } else {
80
+ options . integrations = defaultIntegrations => {
81
+ const userFinalIntegrations = integrations ( defaultIntegrations ) ;
82
+
83
+ return maybeUpdateBrowserTracingIntegration ( userFinalIntegrations ) ;
84
+ } ;
85
+ }
86
+ }
87
+
88
+ function maybeUpdateBrowserTracingIntegration ( integrations : Integration [ ] ) : Integration [ ] {
89
+ const browserTracing = integrations . find ( integration => integration . name === 'BrowserTracing' ) ;
90
+ // If BrowserTracing was added, but it is not our forked version,
91
+ // replace it with our forked version with the same options
92
+ if ( browserTracing && ! ( browserTracing instanceof BrowserTracing ) ) {
93
+ const options : ConstructorParameters < typeof BrowserTracing > [ 0 ] = ( browserTracing as BrowserTracing ) . options ;
94
+ // These two options are overwritten by the custom integration
95
+ delete options . routingInstrumentation ;
96
+ // eslint-disable-next-line deprecation/deprecation
97
+ delete options . tracingOrigins ;
98
+ integrations [ integrations . indexOf ( browserTracing ) ] = new BrowserTracing ( options ) ;
99
+ }
100
+
101
+ return integrations ;
102
+ }
103
+
104
+ function getDefaultIntegrations ( options : BrowserOptions ) : Integration [ ] {
105
+ const customDefaultIntegrations = [ ...getReactDefaultIntegrations ( options ) , rewriteFramesIntegration ( ) ] ;
109
106
110
107
// This evaluates to true unless __SENTRY_TRACING__ is text-replaced with "false", in which case everything inside
111
108
// will get treeshaken away
112
109
if ( typeof __SENTRY_TRACING__ === 'undefined' || __SENTRY_TRACING__ ) {
113
110
if ( hasTracingEnabled ( options ) ) {
114
- const defaultBrowserTracingIntegration = new BrowserTracing ( {
115
- // eslint-disable-next-line deprecation/deprecation
116
- tracingOrigins :
117
- process . env . NODE_ENV === 'development'
118
- ? [
119
- // Will match any URL that contains "localhost" but not "webpack.hot-update.json" - The webpack dev-server
120
- // has cors and it doesn't like extra headers when it's accessed from a different URL.
121
- // TODO(v8): Ideally we rework our tracePropagationTargets logic so this hack won't be necessary anymore (see issue #9764)
122
- / ^ (? = .* l o c a l h o s t ) (? ! .* w e b p a c k \. h o t - u p d a t e \. j s o n ) .* / ,
123
- / ^ \/ (? ! \/ ) / ,
124
- ]
125
- : // eslint-disable-next-line deprecation/deprecation
126
- [ ...defaultRequestInstrumentationOptions . tracingOrigins , / ^ ( a p i \/ ) / ] ,
127
- routingInstrumentation : nextRouterInstrumentation ,
128
- } ) ;
129
-
130
- integrations = addOrUpdateIntegration ( defaultBrowserTracingIntegration , integrations , {
131
- 'options.routingInstrumentation' : nextRouterInstrumentation ,
132
- } ) ;
111
+ customDefaultIntegrations . push ( new BrowserTracing ( ) ) ;
133
112
}
134
113
}
135
114
136
- options . integrations = integrations ;
115
+ return customDefaultIntegrations ;
137
116
}
138
117
139
118
/**
0 commit comments