1
1
import {
2
2
SEMANTIC_ATTRIBUTE_SENTRY_OP ,
3
3
SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN ,
4
+ SEMANTIC_ATTRIBUTE_SENTRY_SOURCE ,
4
5
applySdkMetadata ,
5
6
getClient ,
6
7
getGlobalScope ,
7
8
getRootSpan ,
8
9
spanToJSON ,
9
10
} from '@sentry/core' ;
10
- import { getDefaultIntegrations , init as nodeInit } from '@sentry/node' ;
11
+ import { getDefaultIntegrations , httpIntegration , init as nodeInit } from '@sentry/node' ;
11
12
import type { NodeClient , NodeOptions } from '@sentry/node' ;
12
- import { GLOBAL_OBJ , logger } from '@sentry/utils' ;
13
+ import { GLOBAL_OBJ , extractTraceparentData , logger , stripUrlQueryAndFragment } from '@sentry/utils' ;
13
14
14
15
import {
15
16
ATTR_HTTP_REQUEST_METHOD ,
@@ -22,7 +23,10 @@ import type { EventProcessor } from '@sentry/types';
22
23
import { DEBUG_BUILD } from '../common/debug-build' ;
23
24
import { devErrorSymbolicationEventProcessor } from '../common/devErrorSymbolicationEventProcessor' ;
24
25
import { getVercelEnv } from '../common/getVercelEnv' ;
25
- import { TRANSACTION_ATTR_SHOULD_DROP_TRANSACTION } from '../common/span-attributes-with-logic-attached' ;
26
+ import {
27
+ TRANSACTION_ATTR_SENTRY_TRACE_BACKFILL ,
28
+ TRANSACTION_ATTR_SHOULD_DROP_TRANSACTION ,
29
+ } from '../common/span-attributes-with-logic-attached' ;
26
30
import { isBuild } from '../common/utils/isBuild' ;
27
31
import { distDirRewriteFramesIntegration } from './distDirRewriteFramesIntegration' ;
28
32
@@ -99,7 +103,18 @@ export function init(options: NodeOptions): NodeClient | undefined {
99
103
return ;
100
104
}
101
105
102
- const customDefaultIntegrations = getDefaultIntegrations ( options ) ;
106
+ const customDefaultIntegrations = getDefaultIntegrations ( options )
107
+ . filter ( integration => integration . name !== 'Http' )
108
+ . concat (
109
+ // We are using the HTTP integration without instrumenting incoming HTTP requests because Next.js does that by itself.
110
+ httpIntegration ( {
111
+ instrumentation : {
112
+ _experimentalConfig : {
113
+ disableIncomingRequestInstrumentation : true ,
114
+ } ,
115
+ } ,
116
+ } ) ,
117
+ ) ;
103
118
104
119
// Turn off Next.js' own fetch instrumentation
105
120
// https://github.com/lforst/nextjs-fork/blob/1994fd186defda77ad971c36dc3163db263c993f/packages/next/src/server/lib/patch-fetch.ts#L245
@@ -319,15 +334,47 @@ export function init(options: NodeOptions): NodeClient | undefined {
319
334
}
320
335
321
336
// Enhance route handler transactions
322
- if ( event . type === 'transaction' && event . contexts ?. trace ?. data ?. [ 'sentry.route_handler' ] === true ) {
337
+ if (
338
+ event . type === 'transaction' &&
339
+ ( event . contexts ?. trace ?. data ?. [ 'sentry.route_handler' ] === true ||
340
+ event . contexts ?. trace ?. data ?. [ 'sentry.rsc' ] === true )
341
+ ) {
323
342
event . contexts . trace . data = event . contexts . trace . data || { } ;
324
343
event . contexts . trace . data [ SEMANTIC_ATTRIBUTE_SENTRY_OP ] = 'http.server' ;
325
344
event . contexts . trace . op = 'http.server' ;
345
+
346
+ if ( event . transaction ) {
347
+ event . transaction = stripUrlQueryAndFragment ( event . transaction ) ;
348
+ }
349
+
326
350
if ( typeof event . contexts . trace . data [ ATTR_HTTP_ROUTE ] === 'string' ) {
327
351
// eslint-disable-next-line deprecation/deprecation
328
352
event . transaction = `${ event . contexts . trace . data [ SEMATTRS_HTTP_METHOD ] } ${ event . contexts . trace . data [
329
353
ATTR_HTTP_ROUTE
330
354
] . replace ( / \/ r o u t e $ / , '' ) } `;
355
+ event . contexts . trace . data [ SEMANTIC_ATTRIBUTE_SENTRY_SOURCE ] = 'route' ;
356
+ }
357
+ }
358
+
359
+ // Next.js 13 is not correctly picking up tracing data for trace propagation so we use a back-fill strategy
360
+ if (
361
+ event . type === 'transaction' &&
362
+ typeof event . contexts ?. trace ?. data ?. [ TRANSACTION_ATTR_SENTRY_TRACE_BACKFILL ] === 'string'
363
+ ) {
364
+ const traceparentData = extractTraceparentData (
365
+ event . contexts . trace . data [ TRANSACTION_ATTR_SENTRY_TRACE_BACKFILL ] ,
366
+ ) ;
367
+
368
+ if ( traceparentData ?. parentSampled === false ) {
369
+ return null ;
370
+ }
371
+
372
+ if ( traceparentData ?. traceId ) {
373
+ event . contexts . trace . trace_id = traceparentData . traceId ;
374
+ }
375
+
376
+ if ( traceparentData ?. parentSpanId ) {
377
+ event . contexts . trace . parent_span_id = traceparentData . parentSpanId ;
331
378
}
332
379
}
333
380
0 commit comments