@@ -3,6 +3,7 @@ import type { ClientOptions, Scope, SentrySpanArguments, Span, SpanTimeInput, St
3
3
import { propagationContextFromHeaders } from '@sentry/utils' ;
4
4
import type { AsyncContextStrategy } from '../asyncContext' ;
5
5
import { getMainCarrier } from '../asyncContext' ;
6
+
6
7
import { getClient , getCurrentScope , getIsolationScope , withScope } from '../currentScopes' ;
7
8
8
9
import { getAsyncContextStrategy } from '../hub' ;
@@ -25,6 +26,8 @@ import { SentrySpan } from './sentrySpan';
25
26
import { SPAN_STATUS_ERROR } from './spanstatus' ;
26
27
import { setCapturedScopesOnSpan } from './utils' ;
27
28
29
+ const SUPPRESS_TRACING_KEY = '__SENTRY_SUPPRESS_TRACING__' ;
30
+
28
31
/**
29
32
* Wraps a function with a transaction/span and finishes the span after the function is done.
30
33
* The created span is the active span and will be used as parent by other spans created inside the function
@@ -204,6 +207,20 @@ export function withActiveSpan<T>(span: Span | null, callback: (scope: Scope) =>
204
207
} ) ;
205
208
}
206
209
210
+ /** Suppress tracing in the given callback, ensuring no spans are generated inside of it. */
211
+ export function suppressTracing < T > ( callback : ( ) => T ) : T {
212
+ const acs = getAcs ( ) ;
213
+
214
+ if ( acs . suppressTracing ) {
215
+ return acs . suppressTracing ( callback ) ;
216
+ }
217
+
218
+ return withScope ( scope => {
219
+ scope . setSDKProcessingMetadata ( { [ SUPPRESS_TRACING_KEY ] : true } ) ;
220
+ return callback ( ) ;
221
+ } ) ;
222
+ }
223
+
207
224
function createChildSpanOrTransaction ( {
208
225
parentSpan,
209
226
spanContext,
@@ -223,7 +240,7 @@ function createChildSpanOrTransaction({
223
240
224
241
let span : Span ;
225
242
if ( parentSpan && ! forceTransaction ) {
226
- span = _startChildSpan ( parentSpan , spanContext ) ;
243
+ span = _startChildSpan ( parentSpan , scope , spanContext ) ;
227
244
addChildSpanToSpan ( parentSpan , span ) ;
228
245
} else if ( parentSpan ) {
229
246
// If we forced a transaction but have a parent span, make sure to continue from the parent span, not the scope
@@ -237,6 +254,7 @@ function createChildSpanOrTransaction({
237
254
parentSpanId,
238
255
...spanContext ,
239
256
} ,
257
+ scope ,
240
258
parentSampled ,
241
259
) ;
242
260
@@ -258,6 +276,7 @@ function createChildSpanOrTransaction({
258
276
parentSpanId,
259
277
...spanContext ,
260
278
} ,
279
+ scope ,
261
280
parentSampled ,
262
281
) ;
263
282
@@ -296,22 +315,24 @@ function getAcs(): AsyncContextStrategy {
296
315
return getAsyncContextStrategy ( carrier ) ;
297
316
}
298
317
299
- function _startRootSpan ( spanArguments : SentrySpanArguments , parentSampled ?: boolean ) : SentrySpan {
318
+ function _startRootSpan ( spanArguments : SentrySpanArguments , scope : Scope , parentSampled ?: boolean ) : SentrySpan {
300
319
const client = getClient ( ) ;
301
320
const options : Partial < ClientOptions > = ( client && client . getOptions ( ) ) || { } ;
302
321
303
322
const { name = '' , attributes } = spanArguments ;
304
- const [ sampled , sampleRate ] = sampleSpan ( options , {
305
- name,
306
- parentSampled,
307
- attributes,
308
- transactionContext : {
309
- name,
310
- parentSampled,
311
- } ,
312
- } ) ;
313
-
314
- const transaction = new SentrySpan ( {
323
+ const [ sampled , sampleRate ] = scope . getScopeData ( ) . sdkProcessingMetadata [ SUPPRESS_TRACING_KEY ]
324
+ ? [ false ]
325
+ : sampleSpan ( options , {
326
+ name,
327
+ parentSampled,
328
+ attributes,
329
+ transactionContext : {
330
+ name,
331
+ parentSampled,
332
+ } ,
333
+ } ) ;
334
+
335
+ const rootSpan = new SentrySpan ( {
315
336
...spanArguments ,
316
337
attributes : {
317
338
[ SEMANTIC_ATTRIBUTE_SENTRY_SOURCE ] : 'custom' ,
@@ -320,30 +341,32 @@ function _startRootSpan(spanArguments: SentrySpanArguments, parentSampled?: bool
320
341
sampled,
321
342
} ) ;
322
343
if ( sampleRate !== undefined ) {
323
- transaction . setAttribute ( SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE , sampleRate ) ;
344
+ rootSpan . setAttribute ( SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE , sampleRate ) ;
324
345
}
325
346
326
347
if ( client ) {
327
- client . emit ( 'spanStart' , transaction ) ;
348
+ client . emit ( 'spanStart' , rootSpan ) ;
328
349
}
329
350
330
- return transaction ;
351
+ return rootSpan ;
331
352
}
332
353
333
354
/**
334
355
* Creates a new `Span` while setting the current `Span.id` as `parentSpanId`.
335
356
* This inherits the sampling decision from the parent span.
336
357
*/
337
- function _startChildSpan ( parentSpan : Span , spanArguments : SentrySpanArguments ) : SentrySpan {
358
+ function _startChildSpan ( parentSpan : Span , scope : Scope , spanArguments : SentrySpanArguments ) : Span {
338
359
const { spanId, traceId } = parentSpan . spanContext ( ) ;
339
- const sampled = spanIsSampled ( parentSpan ) ;
360
+ const sampled = scope . getScopeData ( ) . sdkProcessingMetadata [ SUPPRESS_TRACING_KEY ] ? false : spanIsSampled ( parentSpan ) ;
340
361
341
- const childSpan = new SentrySpan ( {
342
- ...spanArguments ,
343
- parentSpanId : spanId ,
344
- traceId,
345
- sampled,
346
- } ) ;
362
+ const childSpan = sampled
363
+ ? new SentrySpan ( {
364
+ ...spanArguments ,
365
+ parentSpanId : spanId ,
366
+ traceId,
367
+ sampled,
368
+ } )
369
+ : new SentryNonRecordingSpan ( ) ;
347
370
348
371
addChildSpanToSpan ( parentSpan , childSpan ) ;
349
372
0 commit comments