@@ -311,13 +311,15 @@ def test_probability_sampler_limits(self):
311311 almost_almost_always_on .bound , 0xFFFFFFFFFFFFFFFF ,
312312 )
313313
314+ # pylint:disable=too-many-statements
314315 def exec_parent_based (self , parent_sampling_context ):
315316 trace_state = trace .TraceState ({"key" : "value" })
316317 sampler = sampling .ParentBased (sampling .ALWAYS_ON )
318+ # Check that the sampling decision matches the parent context if given
317319 with parent_sampling_context (
318320 self ._create_parent_span (trace_flags = TO_DEFAULT )
319321 ) as context :
320- # Check that the sampling decision matches the parent context if given
322+ # local, not sampled
321323 not_sampled_result = sampler .should_sample (
322324 context ,
323325 0x7FFFFFFFFFFFFFFF ,
@@ -329,11 +331,101 @@ def exec_parent_based(self, parent_sampling_context):
329331 self .assertEqual (not_sampled_result .attributes , {})
330332 self .assertEqual (not_sampled_result .trace_state , trace_state )
331333
334+ with parent_sampling_context (
335+ self ._create_parent_span (trace_flags = TO_DEFAULT )
336+ ) as context :
337+ sampler = sampling .ParentBased (
338+ root = sampling .ALWAYS_OFF ,
339+ local_parent_not_sampled = sampling .ALWAYS_ON ,
340+ )
341+ # local, not sampled -> opposite sampler
342+ sampled_result = sampler .should_sample (
343+ context ,
344+ 0x7FFFFFFFFFFFFFFF ,
345+ "unsampled parent, sampling on" ,
346+ attributes = {"sampled" : "false" },
347+ trace_state = trace_state ,
348+ )
349+ self .assertTrue (sampled_result .decision .is_sampled ())
350+ self .assertEqual (sampled_result .attributes , {"sampled" : "false" })
351+ self .assertEqual (sampled_result .trace_state , trace_state )
352+
353+ with parent_sampling_context (
354+ self ._create_parent_span (trace_flags = TO_SAMPLED )
355+ ) as context :
356+ sampler = sampling .ParentBased (sampling .ALWAYS_OFF )
357+ # local, sampled
358+ sampled_result = sampler .should_sample (
359+ context ,
360+ 0x8000000000000000 ,
361+ "sampled parent, sampling off" ,
362+ attributes = {"sampled" : "true" },
363+ trace_state = trace_state ,
364+ )
365+ self .assertTrue (sampled_result .decision .is_sampled ())
366+ self .assertEqual (sampled_result .attributes , {"sampled" : "true" })
367+ self .assertEqual (sampled_result .trace_state , trace_state )
368+
332369 with parent_sampling_context (
333370 self ._create_parent_span (trace_flags = TO_SAMPLED )
334371 ) as context :
335- sampler2 = sampling .ParentBased (sampling .ALWAYS_OFF )
336- sampled_result = sampler2 .should_sample (
372+ sampler = sampling .ParentBased (
373+ root = sampling .ALWAYS_ON ,
374+ local_parent_sampled = sampling .ALWAYS_OFF ,
375+ )
376+ # local, sampled -> opposite sampler
377+ not_sampled_result = sampler .should_sample (
378+ context ,
379+ 0x7FFFFFFFFFFFFFFF ,
380+ "unsampled parent, sampling on" ,
381+ attributes = {"sampled" : "false" },
382+ trace_state = trace_state ,
383+ )
384+ self .assertFalse (not_sampled_result .decision .is_sampled ())
385+ self .assertEqual (not_sampled_result .attributes , {})
386+ self .assertEqual (not_sampled_result .trace_state , trace_state )
387+
388+ with parent_sampling_context (
389+ self ._create_parent_span (trace_flags = TO_DEFAULT , is_remote = True )
390+ ) as context :
391+ sampler = sampling .ParentBased (sampling .ALWAYS_ON )
392+ # remote, not sampled
393+ not_sampled_result = sampler .should_sample (
394+ context ,
395+ 0x7FFFFFFFFFFFFFFF ,
396+ "unsampled parent, sampling on" ,
397+ attributes = {"sampled" : "false" },
398+ trace_state = trace_state ,
399+ )
400+ self .assertFalse (not_sampled_result .decision .is_sampled ())
401+ self .assertEqual (not_sampled_result .attributes , {})
402+ self .assertEqual (not_sampled_result .trace_state , trace_state )
403+
404+ with parent_sampling_context (
405+ self ._create_parent_span (trace_flags = TO_DEFAULT , is_remote = True )
406+ ) as context :
407+ sampler = sampling .ParentBased (
408+ root = sampling .ALWAYS_OFF ,
409+ remote_parent_not_sampled = sampling .ALWAYS_ON ,
410+ )
411+ # remote, not sampled -> opposite sampler
412+ sampled_result = sampler .should_sample (
413+ context ,
414+ 0x7FFFFFFFFFFFFFFF ,
415+ "unsampled parent, sampling on" ,
416+ attributes = {"sampled" : "false" },
417+ trace_state = trace_state ,
418+ )
419+ self .assertTrue (sampled_result .decision .is_sampled ())
420+ self .assertEqual (sampled_result .attributes , {"sampled" : "false" })
421+ self .assertEqual (sampled_result .trace_state , trace_state )
422+
423+ with parent_sampling_context (
424+ self ._create_parent_span (trace_flags = TO_SAMPLED , is_remote = True )
425+ ) as context :
426+ sampler = sampling .ParentBased (sampling .ALWAYS_OFF )
427+ # remote, sampled
428+ sampled_result = sampler .should_sample (
337429 context ,
338430 0x8000000000000000 ,
339431 "sampled parent, sampling off" ,
@@ -344,10 +436,29 @@ def exec_parent_based(self, parent_sampling_context):
344436 self .assertEqual (sampled_result .attributes , {"sampled" : "true" })
345437 self .assertEqual (sampled_result .trace_state , trace_state )
346438
347- # for root span follow decision of delegate sampler
439+ with parent_sampling_context (
440+ self ._create_parent_span (trace_flags = TO_SAMPLED , is_remote = True )
441+ ) as context :
442+ sampler = sampling .ParentBased (
443+ root = sampling .ALWAYS_ON ,
444+ remote_parent_sampled = sampling .ALWAYS_OFF ,
445+ )
446+ # remote, sampled -> opposite sampler
447+ not_sampled_result = sampler .should_sample (
448+ context ,
449+ 0x7FFFFFFFFFFFFFFF ,
450+ "unsampled parent, sampling on" ,
451+ attributes = {"sampled" : "false" },
452+ trace_state = trace_state ,
453+ )
454+ self .assertFalse (not_sampled_result .decision .is_sampled ())
455+ self .assertEqual (not_sampled_result .attributes , {})
456+ self .assertEqual (not_sampled_result .trace_state , trace_state )
457+
458+ # for root span follow decision of root sampler
348459 with parent_sampling_context (trace .INVALID_SPAN ) as context :
349- sampler3 = sampling .ParentBased (sampling .ALWAYS_OFF )
350- not_sampled_result = sampler3 .should_sample (
460+ sampler = sampling .ParentBased (sampling .ALWAYS_OFF )
461+ not_sampled_result = sampler .should_sample (
351462 context ,
352463 0x8000000000000000 ,
353464 "parent, sampling off" ,
@@ -359,8 +470,8 @@ def exec_parent_based(self, parent_sampling_context):
359470 self .assertEqual (not_sampled_result .trace_state , trace_state )
360471
361472 with parent_sampling_context (trace .INVALID_SPAN ) as context :
362- sampler4 = sampling .ParentBased (sampling .ALWAYS_ON )
363- sampled_result = sampler4 .should_sample (
473+ sampler = sampling .ParentBased (sampling .ALWAYS_ON )
474+ sampled_result = sampler .should_sample (
364475 context ,
365476 0x8000000000000000 ,
366477 "no parent, sampling on" ,
0 commit comments