1
- import type { Options , SamplingContext } from '@sentry/types' ;
1
+ import type { Options , SamplingContext , TransactionContext } from '@sentry/types' ;
2
2
import { isNaN , logger } from '@sentry/utils' ;
3
3
4
4
import { DEBUG_BUILD } from '../debug-build' ;
5
- import { SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE } from '../semanticAttributes' ;
6
5
import { hasTracingEnabled } from '../utils/hasTracingEnabled' ;
7
- import { spanToJSON } from '../utils/spanUtils' ;
8
- import type { Transaction } from './transaction' ;
9
6
10
7
/**
11
8
* Makes a sampling decision for the given transaction and stores it on the transaction.
@@ -16,50 +13,42 @@ import type { Transaction } from './transaction';
16
13
* This method muttes the given `transaction` and will set the `sampled` value on it.
17
14
* It returns the same transaction, for convenience.
18
15
*/
19
- export function sampleTransaction < T extends Transaction > (
20
- transaction : T ,
16
+ export function sampleTransaction (
17
+ transactionContext : TransactionContext ,
21
18
options : Pick < Options , 'tracesSampleRate' | 'tracesSampler' | 'enableTracing' > ,
22
19
samplingContext : SamplingContext ,
23
- ) : T {
20
+ ) : [ sampled : boolean , sampleRate ?: number ] {
24
21
// nothing to do if tracing is not enabled
25
22
if ( ! hasTracingEnabled ( options ) ) {
26
- // eslint-disable-next-line deprecation/deprecation
27
- transaction . sampled = false ;
28
- return transaction ;
23
+ return [ false ] ;
29
24
}
30
25
31
- // if the user has forced a sampling decision by passing a `sampled` value in their transaction context, go with that
32
- // eslint-disable-next-line deprecation/deprecation
33
- if ( transaction . sampled !== undefined ) {
34
- // eslint-disable-next-line deprecation/deprecation
35
- transaction . setAttribute ( SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE , Number ( transaction . sampled ) ) ;
36
- return transaction ;
26
+ const transactionContextSampled = transactionContext . sampled ;
27
+ // if the user has forced a sampling decision by passing a `sampled` value in
28
+ // their transaction context, go with that.
29
+ if ( transactionContextSampled !== undefined ) {
30
+ return [ transactionContextSampled , Number ( transactionContextSampled ) ] ;
37
31
}
38
32
39
33
// we would have bailed already if neither `tracesSampler` nor `tracesSampleRate` nor `enableTracing` were defined, so one of these should
40
34
// work; prefer the hook if so
41
35
let sampleRate ;
42
36
if ( typeof options . tracesSampler === 'function' ) {
43
37
sampleRate = options . tracesSampler ( samplingContext ) ;
44
- transaction . setAttribute ( SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE , Number ( sampleRate ) ) ;
45
38
} else if ( samplingContext . parentSampled !== undefined ) {
46
39
sampleRate = samplingContext . parentSampled ;
47
40
} else if ( typeof options . tracesSampleRate !== 'undefined' ) {
48
41
sampleRate = options . tracesSampleRate ;
49
- transaction . setAttribute ( SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE , Number ( sampleRate ) ) ;
50
42
} else {
51
43
// When `enableTracing === true`, we use a sample rate of 100%
52
44
sampleRate = 1 ;
53
- transaction . setAttribute ( SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE , sampleRate ) ;
54
45
}
55
46
56
47
// Since this is coming from the user (or from a function provided by the user), who knows what we might get. (The
57
48
// only valid values are booleans or numbers between 0 and 1.)
58
49
if ( ! isValidSampleRate ( sampleRate ) ) {
59
50
DEBUG_BUILD && logger . warn ( '[Tracing] Discarding transaction because of invalid sample rate.' ) ;
60
- // eslint-disable-next-line deprecation/deprecation
61
- transaction . sampled = false ;
62
- return transaction ;
51
+ return [ false ] ;
63
52
}
64
53
65
54
// if the function returned 0 (or false), or if `tracesSampleRate` is 0, it's a sign the transaction should be dropped
@@ -72,40 +61,31 @@ export function sampleTransaction<T extends Transaction>(
72
61
: 'a negative sampling decision was inherited or tracesSampleRate is set to 0'
73
62
} `,
74
63
) ;
75
- // eslint-disable-next-line deprecation/deprecation
76
- transaction . sampled = false ;
77
- return transaction ;
64
+ return [ false , Number ( sampleRate ) ] ;
78
65
}
79
66
80
67
// Now we roll the dice. Math.random is inclusive of 0, but not of 1, so strict < is safe here. In case sampleRate is
81
68
// a boolean, the < comparison will cause it to be automatically cast to 1 if it's true and 0 if it's false.
82
- // eslint-disable-next-line deprecation/deprecation
83
- transaction . sampled = Math . random ( ) < ( sampleRate as number | boolean ) ;
69
+ const shouldSample = Math . random ( ) < sampleRate ;
84
70
85
71
// if we're not going to keep it, we're done
86
- // eslint-disable-next-line deprecation/deprecation
87
- if ( ! transaction . sampled ) {
72
+ if ( ! shouldSample ) {
88
73
DEBUG_BUILD &&
89
74
logger . log (
90
75
`[Tracing] Discarding transaction because it's not included in the random sample (sampling rate = ${ Number (
91
76
sampleRate ,
92
77
) } )`,
93
78
) ;
94
- return transaction ;
79
+ return [ false , Number ( sampleRate ) ] ;
95
80
}
96
81
97
- if ( DEBUG_BUILD ) {
98
- const { op, description } = spanToJSON ( transaction ) ;
99
- logger . log ( `[Tracing] starting ${ op } transaction - ${ description } ` ) ;
100
- }
101
-
102
- return transaction ;
82
+ return [ true , Number ( sampleRate ) ] ;
103
83
}
104
84
105
85
/**
106
86
* Checks the given sample rate to make sure it is valid type and value (a boolean, or a number between 0 and 1).
107
87
*/
108
- function isValidSampleRate ( rate : unknown ) : boolean {
88
+ function isValidSampleRate ( rate : unknown ) : rate is number | boolean {
109
89
// we need to check NaN explicitly because it's of type 'number' and therefore wouldn't get caught by this typecheck
110
90
if ( isNaN ( rate ) || ! ( typeof rate === 'number' || typeof rate === 'boolean' ) ) {
111
91
DEBUG_BUILD &&
0 commit comments