@@ -41,7 +41,7 @@ describe('Hub', () => {
4141 } ) ;
4242
4343 describe ( 'transaction sampling' , ( ) => {
44- describe ( 'options' , ( ) => {
44+ describe ( 'tracesSampleRate and tracesSampler options' , ( ) => {
4545 it ( "should call tracesSampler if it's defined" , ( ) => {
4646 const tracesSampler = jest . fn ( ) ;
4747 const hub = new Hub ( new BrowserClient ( { tracesSampler } ) ) ;
@@ -52,11 +52,20 @@ describe('Hub', () => {
5252
5353 it ( 'should prefer tracesSampler to tracesSampleRate' , ( ) => {
5454 const tracesSampler = jest . fn ( ) ;
55- const hub = new Hub ( new BrowserClient ( { tracesSampleRate : 1 , tracesSampler : tracesSampler } ) ) ;
55+ const hub = new Hub ( new BrowserClient ( { tracesSampleRate : 1 , tracesSampler } ) ) ;
5656 hub . startTransaction ( { name : 'dogpark' } ) ;
5757
5858 expect ( tracesSampler ) . toHaveBeenCalled ( ) ;
5959 } ) ;
60+
61+ it ( 'tolerates tracesSampler returning a boolean' , ( ) => {
62+ const tracesSampler = jest . fn ( ) . mockReturnValue ( true ) ;
63+ const hub = new Hub ( new BrowserClient ( { tracesSampler } ) ) ;
64+ const transaction = hub . startTransaction ( { name : 'dogpark' } ) ;
65+
66+ expect ( tracesSampler ) . toHaveBeenCalled ( ) ;
67+ expect ( transaction . sampled ) . toBe ( true ) ;
68+ } ) ;
6069 } ) ;
6170
6271 describe ( 'default sample context' , ( ) => {
@@ -133,9 +142,25 @@ describe('Hub', () => {
133142
134143 expect ( tracesSampler ) . toHaveBeenCalledWith ( expect . objectContaining ( { location : dogParkLocation } ) ) ;
135144 } ) ;
145+
146+ it ( "should add parent's sampling decision to default sample context" , ( ) => {
147+ const tracesSampler = jest . fn ( ) ;
148+ const hub = new Hub ( new BrowserClient ( { tracesSampler } ) ) ;
149+ const parentSamplingDecsion = false ;
150+
151+ hub . startTransaction ( {
152+ name : 'dogpark' ,
153+ parentSpanId : '12312012' ,
154+ sampled : parentSamplingDecsion ,
155+ } ) ;
156+
157+ expect ( tracesSampler ) . toHaveBeenLastCalledWith (
158+ expect . objectContaining ( { parentSampled : parentSamplingDecsion } ) ,
159+ ) ;
160+ } ) ;
136161 } ) ;
137162
138- describe ( 'while sampling ' , ( ) => {
163+ describe ( 'sample() ' , ( ) => {
139164 it ( 'should not sample transactions when tracing is disabled' , ( ) => {
140165 // neither tracesSampleRate nor tracesSampler is defined -> tracing disabled
141166 const hub = new Hub ( new BrowserClient ( { } ) ) ;
@@ -157,36 +182,41 @@ describe('Hub', () => {
157182
158183 expect ( transaction . sampled ) . toBe ( true ) ;
159184 } ) ;
185+ } ) ;
160186
161- it ( "should reject tracesSampleRates which aren't numbers" , ( ) => {
187+ describe ( 'isValidSampleRate()' , ( ) => {
188+ it ( "should reject tracesSampleRates which aren't numbers or booleans" , ( ) => {
162189 const hub = new Hub ( new BrowserClient ( { tracesSampleRate : 'dogs!' as any } ) ) ;
163190 hub . startTransaction ( { name : 'dogpark' } ) ;
164191
165- expect ( logger . warn ) . toHaveBeenCalledWith ( expect . stringContaining ( 'Sample rate must be a number' ) ) ;
192+ expect ( logger . warn ) . toHaveBeenCalledWith ( expect . stringContaining ( 'Sample rate must be a boolean or a number' ) ) ;
166193 } ) ;
167194
195+ // the rate might be a boolean, but for our purposes, false is equivalent to 0 and true is equivalent to 1
168196 it ( 'should reject tracesSampleRates less than 0' , ( ) => {
169197 const hub = new Hub ( new BrowserClient ( { tracesSampleRate : - 26 } ) ) ;
170198 hub . startTransaction ( { name : 'dogpark' } ) ;
171199
172200 expect ( logger . warn ) . toHaveBeenCalledWith ( expect . stringContaining ( 'Sample rate must be between 0 and 1' ) ) ;
173201 } ) ;
174202
203+ // the rate might be a boolean, but for our purposes, false is equivalent to 0 and true is equivalent to 1
175204 it ( 'should reject tracesSampleRates greater than 1' , ( ) => {
176205 const hub = new Hub ( new BrowserClient ( { tracesSampleRate : 26 } ) ) ;
177206 hub . startTransaction ( { name : 'dogpark' } ) ;
178207
179208 expect ( logger . warn ) . toHaveBeenCalledWith ( expect . stringContaining ( 'Sample rate must be between 0 and 1' ) ) ;
180209 } ) ;
181210
182- it ( "should reject tracesSampler return values which aren't numbers" , ( ) => {
211+ it ( "should reject tracesSampler return values which aren't numbers or booleans " , ( ) => {
183212 const tracesSampler = jest . fn ( ) . mockReturnValue ( 'dogs!' ) ;
184213 const hub = new Hub ( new BrowserClient ( { tracesSampler } ) ) ;
185214 hub . startTransaction ( { name : 'dogpark' } ) ;
186215
187- expect ( logger . warn ) . toHaveBeenCalledWith ( expect . stringContaining ( 'Sample rate must be a number' ) ) ;
216+ expect ( logger . warn ) . toHaveBeenCalledWith ( expect . stringContaining ( 'Sample rate must be a boolean or a number' ) ) ;
188217 } ) ;
189218
219+ // the rate might be a boolean, but for our purposes, false is equivalent to 0 and true is equivalent to 1
190220 it ( 'should reject tracesSampler return values less than 0' , ( ) => {
191221 const tracesSampler = jest . fn ( ) . mockReturnValue ( - 12 ) ;
192222 const hub = new Hub ( new BrowserClient ( { tracesSampler } ) ) ;
@@ -195,6 +225,7 @@ describe('Hub', () => {
195225 expect ( logger . warn ) . toHaveBeenCalledWith ( expect . stringContaining ( 'Sample rate must be between 0 and 1' ) ) ;
196226 } ) ;
197227
228+ // the rate might be a boolean, but for our purposes, false is equivalent to 0 and true is equivalent to 1
198229 it ( 'should reject tracesSampler return values greater than 1' , ( ) => {
199230 const tracesSampler = jest . fn ( ) . mockReturnValue ( 31 ) ;
200231 const hub = new Hub ( new BrowserClient ( { tracesSampler } ) ) ;
@@ -204,14 +235,6 @@ describe('Hub', () => {
204235 } ) ;
205236 } ) ;
206237
207- it ( 'should propagate sampling decision to child spans' , ( ) => {
208- const hub = new Hub ( new BrowserClient ( { tracesSampleRate : 0 } ) ) ;
209- const transaction = hub . startTransaction ( { name : 'dogpark' } ) ;
210- const child = transaction . startChild ( { op : 'test' } ) ;
211-
212- expect ( child . sampled ) . toBe ( false ) ;
213- } ) ;
214-
215238 it ( 'should drop transactions with sampled = false' , ( ) => {
216239 const client = new BrowserClient ( { tracesSampleRate : 0 } ) ;
217240 jest . spyOn ( client , 'captureEvent' ) ;
@@ -226,5 +249,55 @@ describe('Hub', () => {
226249 expect ( transaction . finish ) . toReturnWith ( undefined ) ;
227250 expect ( client . captureEvent ) . not . toBeCalled ( ) ;
228251 } ) ;
252+
253+ describe ( 'sampling inheritance' , ( ) => {
254+ it ( 'should propagate sampling decision to child spans' , ( ) => {
255+ const hub = new Hub ( new BrowserClient ( { tracesSampleRate : Math . random ( ) } ) ) ;
256+ const transaction = hub . startTransaction ( { name : 'dogpark' } ) ;
257+ const child = transaction . startChild ( { op : 'test' } ) ;
258+
259+ expect ( child . sampled ) . toBe ( transaction . sampled ) ;
260+ } ) ;
261+
262+ it ( 'should propagate sampling decision to child transactions in XHR header' , ( ) => {
263+ // TODO this doesn't currently happen, but it should
264+ } ) ;
265+
266+ it ( 'should propagate sampling decision to child transactions in fetch header' , ( ) => {
267+ // TODO this doesn't currently happen, but it should
268+ } ) ;
269+
270+ it ( "should inherit parent's sampling decision when creating a new transaction if tracesSampler is undefined" , ( ) => {
271+ // tracesSampleRate = 1 means every transaction should end up with sampled = true, so make parent's decision the
272+ // opposite to prove that inheritance takes precedence over tracesSampleRate
273+ const hub = new Hub ( new BrowserClient ( { tracesSampleRate : 1 } ) ) ;
274+ const parentSamplingDecsion = false ;
275+
276+ const transaction = hub . startTransaction ( {
277+ name : 'dogpark' ,
278+ parentSpanId : '12312012' ,
279+ sampled : parentSamplingDecsion ,
280+ } ) ;
281+
282+ expect ( transaction . sampled ) . toBe ( parentSamplingDecsion ) ;
283+ } ) ;
284+
285+ it ( "should ignore parent's sampling decision when tracesSampler is defined" , ( ) => {
286+ // this tracesSampler causes every transaction to end up with sampled = true, so make parent's decision the
287+ // opposite to prove that tracesSampler takes precedence over inheritance
288+ const tracesSampler = ( ) => true ;
289+ const parentSamplingDecsion = false ;
290+
291+ const hub = new Hub ( new BrowserClient ( { tracesSampler } ) ) ;
292+
293+ const transaction = hub . startTransaction ( {
294+ name : 'dogpark' ,
295+ parentSpanId : '12312012' ,
296+ sampled : parentSamplingDecsion ,
297+ } ) ;
298+
299+ expect ( transaction . sampled ) . not . toBe ( parentSamplingDecsion ) ;
300+ } ) ;
301+ } ) ;
229302 } ) ;
230303} ) ;
0 commit comments