@@ -445,16 +445,6 @@ TEST_CASE("span extraction") {
445445 TraceID (123 ),
446446 456 ,
447447 2 },
448- {__LINE__,
449- " datadog style with delegate header" ,
450- {PropagationStyle::DATADOG},
451- {{" x-datadog-trace-id" , " 123" },
452- {" x-datadog-parent-id" , " 456" },
453- {" x-datadog-delegate-trace-sampling" , " delegate" },
454- {" x-datadog-sampling-priority" , " 3" }},
455- TraceID (123 ),
456- 456 ,
457- nullopt },
458448 {__LINE__,
459449 " datadog style without sampling priority" ,
460450 {PropagationStyle::DATADOG},
@@ -1204,7 +1194,12 @@ TEST_CASE("span extraction") {
12041194 MockDictReader reader{headers};
12051195 auto span = tracer.extract_span (reader);
12061196 REQUIRE (span);
1207- REQUIRE (!span->trace_segment ().sampling_decision ());
1197+
1198+ if (*config.delegate_trace_sampling ) {
1199+ REQUIRE (!span->trace_segment ().sampling_decision ());
1200+ } else {
1201+ REQUIRE (span->trace_segment ().sampling_decision ());
1202+ }
12081203
12091204 MockDictWriter writer;
12101205 span->inject (writer);
@@ -1409,6 +1404,49 @@ TEST_CASE(
14091404 test_case.expected_error_prefix + test_case.tid_tag_value );
14101405}
14111406
1407+ TEST_CASE (" sampling delegation extraction" ) {
1408+ const bool enable_sampling_delegation = GENERATE (true , false );
1409+
1410+ CAPTURE (enable_sampling_delegation);
1411+
1412+ const auto logger = std::make_shared<NullLogger>();
1413+ const auto collector = std::make_shared<NullCollector>();
1414+
1415+ TracerConfig config;
1416+ config.service = " test-sampling-delegation" ;
1417+ config.logger = logger;
1418+ config.collector = collector;
1419+ config.extraction_styles = {PropagationStyle::DATADOG};
1420+ config.trace_sampler .sample_rate = 1 .;
1421+ config.delegate_trace_sampling = enable_sampling_delegation;
1422+
1423+ auto validated_config = finalize_config (config);
1424+ REQUIRE (validated_config);
1425+
1426+ Tracer tracer (*validated_config);
1427+
1428+ const std::unordered_map<std::string, std::string> headers{
1429+ {" x-datadog-trace-id" , " 17491188783264004180" },
1430+ {" x-datadog-parent-id" , " 3390700340160032468" },
1431+ {" x-datadog-sampling-priority" , " -1" },
1432+ {" x-datadog-tags" , " _dd.p.tid=66718e8c00000000" },
1433+ {" x-datadog-delegate-trace-sampling" , " delegate" },
1434+ };
1435+
1436+ MockDictReader propagation_reader{headers};
1437+ const auto maybe_span = tracer.extract_span (propagation_reader);
1438+ REQUIRE (maybe_span);
1439+
1440+ auto sampling_decision = maybe_span->trace_segment ().sampling_decision ();
1441+ if (enable_sampling_delegation) {
1442+ CHECK (!sampling_decision.has_value ());
1443+ } else {
1444+ REQUIRE (sampling_decision.has_value ());
1445+ CHECK (sampling_decision->origin == SamplingDecision::Origin::EXTRACTED);
1446+ CHECK (sampling_decision->priority == int (SamplingPriority::USER_DROP));
1447+ }
1448+ }
1449+
14121450TEST_CASE (" _dd.is_sampling_decider" ) {
14131451 // This test involves three tracers: "service1", "service2", and "service3".
14141452 // Each calls the next, and each produces two spans: "local_root" and "child".
@@ -1451,6 +1489,7 @@ TEST_CASE("_dd.is_sampling_decider") {
14511489 config2.collector = collector;
14521490 config2.logger = logger;
14531491 config2.service = " service2" ;
1492+ config2.trace_sampler .sample_rate = 1 ; // keep all traces
14541493 config2.delegate_trace_sampling = true ;
14551494
14561495 TracerConfig config3;
@@ -1580,7 +1619,9 @@ TEST_CASE("_dd.is_sampling_decider") {
15801619 }
15811620 REQUIRE (span.service != " service1" );
15821621 if (span.service == " service2" && span.name == " local_root" ) {
1583- REQUIRE (span.tags .count (tags::internal::sampling_decider) == 0 );
1622+ const bool made_the_decision = service3_delegation_enabled ? 0 : 1 ;
1623+ REQUIRE (span.tags .count (tags::internal::sampling_decider) ==
1624+ made_the_decision);
15841625 REQUIRE (span.numeric_tags .count (tags::internal::sampling_priority) ==
15851626 1 );
15861627 REQUIRE (span.numeric_tags .at (tags::internal::sampling_priority) ==
@@ -1595,8 +1636,9 @@ TEST_CASE("_dd.is_sampling_decider") {
15951636 }
15961637 REQUIRE (span.service != " service2" );
15971638 if (span.service == " service3" && span.name == " local_root" ) {
1598- REQUIRE (span.tags .count (tags::internal::sampling_decider) == 1 );
1599- REQUIRE (span.tags .at (tags::internal::sampling_decider) == " 1" );
1639+ const bool made_the_decision = service3_delegation_enabled ? 1 : 0 ;
1640+ REQUIRE (span.tags .count (tags::internal::sampling_decider) ==
1641+ made_the_decision);
16001642 REQUIRE (span.numeric_tags .count (tags::internal::sampling_priority) ==
16011643 1 );
16021644 REQUIRE (span.numeric_tags .at (tags::internal::sampling_priority) ==
@@ -1649,27 +1691,13 @@ TEST_CASE("sampling delegation is not an override") {
16491691 //
16501692 // The idea is that service2 does not perform delegation when service1 already
16511693 // made a decision and did not request delegation.
1652- auto service1_sampling_priority =
1653- GENERATE (values<Optional<int >>({nullopt , -1 , 0 , 1 , 2 }));
16541694 auto service1_delegate = GENERATE (true , false );
16551695 auto service3_sample_rate = GENERATE (0.0 , 1.0 );
16561696
1657- int expected_sampling_priority;
1658- if (service1_sampling_priority.has_value () && !service1_delegate) {
1659- // Service1 made a decision and didn't ask for delegation, so that's the
1660- // decision.
1661- expected_sampling_priority = *service1_sampling_priority;
1662- } else {
1663- // Service1 either didn't make a decision or did request delegation, so the
1664- // decision will be delegated through service2 to service3, whose decision
1665- // depends on its configured sample rate.
1666- expected_sampling_priority = service3_sample_rate == 0.0 ? -1 : 2 ;
1667- }
1697+ const int service3_sampling_priority = service3_sample_rate == 0.0 ? -1 : 2 ;
16681698
1669- CAPTURE (service1_sampling_priority);
16701699 CAPTURE (service1_delegate);
16711700 CAPTURE (service3_sample_rate);
1672- CAPTURE (expected_sampling_priority);
16731701
16741702 const auto collector = std::make_shared<MockCollector>();
16751703 const auto logger = std::make_shared<MockLogger>();
@@ -1697,6 +1725,7 @@ TEST_CASE("sampling delegation is not an override") {
16971725 config3.logger = logger;
16981726 config3.extraction_styles = config1.injection_styles = styles;
16991727 config3.service = " service3" ;
1728+ config3.delegate_trace_sampling = true ;
17001729 config3.trace_sampler .sample_rate = service3_sample_rate;
17011730
17021731 auto valid_config = finalize_config (config1);
@@ -1725,18 +1754,16 @@ TEST_CASE("sampling delegation is not an override") {
17251754 span_config.name = " local_root" ;
17261755 Span span1 = tracer1.create_span (span_config);
17271756 span1.inject (propagation_writer);
1728- if (service1_sampling_priority.has_value ()) {
1729- propagation_writer.items [" x-datadog-sampling-priority" ] =
1730- std::to_string (*service1_sampling_priority);
1731- } else {
1732- propagation_writer.items .erase (" x-datadog-sampling-priority" );
1733- }
17341757
17351758 {
17361759 auto span2 = tracer2.extract_span (propagation_reader, span_config);
17371760 REQUIRE (span2);
17381761 propagation_writer.items .clear ();
17391762 span2->inject (propagation_writer);
1763+ const bool expected_delegate_header = service1_delegate ? 1 : 0 ;
1764+ CHECK (
1765+ propagation_writer.items .count (" x-datadog-delegate-trace-sampling" ) ==
1766+ expected_delegate_header);
17401767
17411768 {
17421769 auto span3 = tracer3.extract_span (propagation_reader, span_config);
@@ -1767,11 +1794,11 @@ TEST_CASE("sampling delegation is not an override") {
17671794 // If `service1_delegate` is false, then service1's sampling decision was
17681795 // made by the service1's sampler, which will result in priority 2.
17691796 // Otherwise, it's the same priority expected for the other spans.
1770- if (span. service == " service1 " && !service1_delegate) {
1797+ if (!service1_delegate) {
17711798 REQUIRE (span.numeric_tags .at (tags::internal::sampling_priority) == 2 );
17721799 } else {
17731800 REQUIRE (span.numeric_tags .at (tags::internal::sampling_priority) ==
1774- expected_sampling_priority );
1801+ service3_sampling_priority );
17751802 }
17761803 }
17771804 }
0 commit comments