1- import type { ClientOptions , CustomSamplingContext , Options , SamplingContext , TransactionContext } from '@sentry/types' ;
2- import { isNaN , logger } from '@sentry/utils' ;
1+ import type { ClientOptions , CustomSamplingContext , TransactionContext } from '@sentry/types' ;
2+ import { logger } from '@sentry/utils' ;
33
44import type { Hub } from '../hub' ;
55import { getMainCarrier } from '../hub' ;
6- import { hasTracingEnabled } from '../utils/hasTracingEnabled' ;
76import { registerErrorInstrumentation } from './errors' ;
87import { IdleTransaction } from './idletransaction' ;
8+ import { sampleTransaction } from './sampling' ;
99import { Transaction } from './transaction' ;
1010
1111/** Returns all trace headers that are currently on the top scope. */
@@ -20,126 +20,6 @@ function traceHeaders(this: Hub): { [key: string]: string } {
2020 : { } ;
2121}
2222
23- /**
24- * Makes a sampling decision for the given transaction and stores it on the transaction.
25- *
26- * Called every time a transaction is created. Only transactions which emerge with a `sampled` value of `true` will be
27- * sent to Sentry.
28- *
29- * @param transaction: The transaction needing a sampling decision
30- * @param options: The current client's options, so we can access `tracesSampleRate` and/or `tracesSampler`
31- * @param samplingContext: Default and user-provided data which may be used to help make the decision
32- *
33- * @returns The given transaction with its `sampled` value set
34- */
35- function sample < T extends Transaction > (
36- transaction : T ,
37- options : Pick < Options , 'tracesSampleRate' | 'tracesSampler' | 'enableTracing' > ,
38- samplingContext : SamplingContext ,
39- ) : T {
40- // nothing to do if tracing is not enabled
41- if ( ! hasTracingEnabled ( options ) ) {
42- transaction . sampled = false ;
43- return transaction ;
44- }
45-
46- // if the user has forced a sampling decision by passing a `sampled` value in their transaction context, go with that
47- if ( transaction . sampled !== undefined ) {
48- transaction . setMetadata ( {
49- sampleRate : Number ( transaction . sampled ) ,
50- } ) ;
51- return transaction ;
52- }
53-
54- // we would have bailed already if neither `tracesSampler` nor `tracesSampleRate` nor `enableTracing` were defined, so one of these should
55- // work; prefer the hook if so
56- let sampleRate ;
57- if ( typeof options . tracesSampler === 'function' ) {
58- sampleRate = options . tracesSampler ( samplingContext ) ;
59- transaction . setMetadata ( {
60- sampleRate : Number ( sampleRate ) ,
61- } ) ;
62- } else if ( samplingContext . parentSampled !== undefined ) {
63- sampleRate = samplingContext . parentSampled ;
64- } else if ( typeof options . tracesSampleRate !== 'undefined' ) {
65- sampleRate = options . tracesSampleRate ;
66- transaction . setMetadata ( {
67- sampleRate : Number ( sampleRate ) ,
68- } ) ;
69- } else {
70- // When `enableTracing === true`, we use a sample rate of 100%
71- sampleRate = 1 ;
72- transaction . setMetadata ( {
73- sampleRate,
74- } ) ;
75- }
76-
77- // Since this is coming from the user (or from a function provided by the user), who knows what we might get. (The
78- // only valid values are booleans or numbers between 0 and 1.)
79- if ( ! isValidSampleRate ( sampleRate ) ) {
80- __DEBUG_BUILD__ && logger . warn ( '[Tracing] Discarding transaction because of invalid sample rate.' ) ;
81- transaction . sampled = false ;
82- return transaction ;
83- }
84-
85- // if the function returned 0 (or false), or if `tracesSampleRate` is 0, it's a sign the transaction should be dropped
86- if ( ! sampleRate ) {
87- __DEBUG_BUILD__ &&
88- logger . log (
89- `[Tracing] Discarding transaction because ${
90- typeof options . tracesSampler === 'function'
91- ? 'tracesSampler returned 0 or false'
92- : 'a negative sampling decision was inherited or tracesSampleRate is set to 0'
93- } `,
94- ) ;
95- transaction . sampled = false ;
96- return transaction ;
97- }
98-
99- // Now we roll the dice. Math.random is inclusive of 0, but not of 1, so strict < is safe here. In case sampleRate is
100- // a boolean, the < comparison will cause it to be automatically cast to 1 if it's true and 0 if it's false.
101- transaction . sampled = Math . random ( ) < ( sampleRate as number | boolean ) ;
102-
103- // if we're not going to keep it, we're done
104- if ( ! transaction . sampled ) {
105- __DEBUG_BUILD__ &&
106- logger . log (
107- `[Tracing] Discarding transaction because it's not included in the random sample (sampling rate = ${ Number (
108- sampleRate ,
109- ) } )`,
110- ) ;
111- return transaction ;
112- }
113-
114- __DEBUG_BUILD__ && logger . log ( `[Tracing] starting ${ transaction . op } transaction - ${ transaction . name } ` ) ;
115- return transaction ;
116- }
117-
118- /**
119- * Checks the given sample rate to make sure it is valid type and value (a boolean, or a number between 0 and 1).
120- */
121- function isValidSampleRate ( rate : unknown ) : boolean {
122- // we need to check NaN explicitly because it's of type 'number' and therefore wouldn't get caught by this typecheck
123- // eslint-disable-next-line @typescript-eslint/no-explicit-any
124- if ( isNaN ( rate ) || ! ( typeof rate === 'number' || typeof rate === 'boolean' ) ) {
125- __DEBUG_BUILD__ &&
126- logger . warn (
127- `[Tracing] Given sample rate is invalid. Sample rate must be a boolean or a number between 0 and 1. Got ${ JSON . stringify (
128- rate ,
129- ) } of type ${ JSON . stringify ( typeof rate ) } .`,
130- ) ;
131- return false ;
132- }
133-
134- // in case sampleRate is a boolean, it will get automatically cast to 1 if it's true and 0 if it's false
135- if ( rate < 0 || rate > 1 ) {
136- __DEBUG_BUILD__ &&
137- logger . warn ( `[Tracing] Given sample rate is invalid. Sample rate must be between 0 and 1. Got ${ rate } .` ) ;
138- return false ;
139- }
140- return true ;
141- }
142-
14323/**
14424 * Creates a new transaction and adds a sampling decision if it doesn't yet have one.
14525 *
@@ -177,7 +57,7 @@ The transaction will not be sampled. Please use the ${configInstrumenter} instru
17757 }
17858
17959 let transaction = new Transaction ( transactionContext , this ) ;
180- transaction = sample ( transaction , options , {
60+ transaction = sampleTransaction ( transaction , options , {
18161 parentSampled : transactionContext . parentSampled ,
18262 transactionContext,
18363 ...customSamplingContext ,
@@ -207,7 +87,7 @@ export function startIdleTransaction(
20787 const options : Partial < ClientOptions > = ( client && client . getOptions ( ) ) || { } ;
20888
20989 let transaction = new IdleTransaction ( transactionContext , hub , idleTimeout , finalTimeout , heartbeatInterval , onScope ) ;
210- transaction = sample ( transaction , options , {
90+ transaction = sampleTransaction ( transaction , options , {
21191 parentSampled : transactionContext . parentSampled ,
21292 transactionContext,
21393 ...customSamplingContext ,
0 commit comments