diff --git a/source/extensions/tracers/opentelemetry/samplers/dynatrace/dynatrace_sampler.cc b/source/extensions/tracers/opentelemetry/samplers/dynatrace/dynatrace_sampler.cc index ebf54c6dbd64..0fa29c4f12e3 100644 --- a/source/extensions/tracers/opentelemetry/samplers/dynatrace/dynatrace_sampler.cc +++ b/source/extensions/tracers/opentelemetry/samplers/dynatrace/dynatrace_sampler.cc @@ -21,7 +21,6 @@ namespace OpenTelemetry { namespace { constexpr std::chrono::minutes SAMPLING_UPDATE_TIMER_DURATION{1}; -const char* SAMPLING_EXTRAPOLATION_SPAN_ATTRIBUTE_NAME = "sampling_extrapolation_set_in_sampler"; class DynatraceTag { public: @@ -73,6 +72,26 @@ class DynatraceTag { uint32_t path_info_; }; +// add Dynatrace specific span attributes +void addSamplingAttributes(uint32_t sampling_exponent, + std::map& attributes) { + + const auto multiplicity = SamplingState::toMultiplicity(sampling_exponent); + // The denominator of the sampling ratio. If, for example, the Dynatrace OneAgent samples with a + // probability of 1/16, the value of supportability.atm_sampling_ratio would be 16. + // Note: Ratio is also known as multiplicity. + attributes["supportability.atm_sampling_ratio"] = std::to_string(multiplicity); + + if (multiplicity > 1) { + static constexpr uint64_t two_pow_56 = 1lu << 56; // 2^56 + // The sampling probability can be interpreted as the number of spans + // that are discarded out of 2^56. The attribute is only available if the sampling.threshold is + // not 0 and therefore sampling happened. + const uint64_t sampling_threshold = two_pow_56 - two_pow_56 / multiplicity; + attributes["sampling.threshold"] = std::to_string(sampling_threshold); + } +} + } // namespace DynatraceSampler::DynatraceSampler( @@ -118,9 +137,7 @@ SamplingResult DynatraceSampler::shouldSample(const absl::optional if (DynatraceTag dynatrace_tag = DynatraceTag::create(trace_state_value); dynatrace_tag.isValid()) { result.decision = dynatrace_tag.isIgnored() ? Decision::Drop : Decision::RecordAndSample; - // TODO: change attribute name and value in scope of OA-26680 - att[SAMPLING_EXTRAPOLATION_SPAN_ATTRIBUTE_NAME] = - std::to_string(dynatrace_tag.getSamplingExponent()); + addSamplingAttributes(dynatrace_tag.getSamplingExponent(), att); result.tracestate = parent_context->tracestate(); } } else { @@ -130,8 +147,8 @@ SamplingResult DynatraceSampler::shouldSample(const absl::optional const auto sampling_state = sampling_controller_.getSamplingState(sampling_key); const bool sample = sampling_state.shouldSample(hash); const auto sampling_exponent = sampling_state.getExponent(); - // TODO: change attribute name and value in scope of OA-26680 - att[SAMPLING_EXTRAPOLATION_SPAN_ATTRIBUTE_NAME] = std::to_string(sampling_exponent); + + addSamplingAttributes(sampling_exponent, att); result.decision = sample ? Decision::RecordAndSample : Decision::Drop; // create new forward tag and add it to tracestate diff --git a/test/extensions/tracers/opentelemetry/samplers/dynatrace/dynatrace_sampler_test.cc b/test/extensions/tracers/opentelemetry/samplers/dynatrace/dynatrace_sampler_test.cc index 29bb74a22404..2ec0614c1cd4 100644 --- a/test/extensions/tracers/opentelemetry/samplers/dynatrace/dynatrace_sampler_test.cc +++ b/test/extensions/tracers/opentelemetry/samplers/dynatrace/dynatrace_sampler_test.cc @@ -80,6 +80,8 @@ TEST_F(DynatraceSamplerTest, TestWithoutParentContext) { ::opentelemetry::proto::trace::v1::Span::SPAN_KIND_SERVER, {}, {}); EXPECT_EQ(sampling_result.decision, Decision::RecordAndSample); EXPECT_EQ(sampling_result.attributes->size(), 1); + EXPECT_STREQ( + sampling_result.attributes->find("supportability.atm_sampling_ratio")->second.c_str(), "1"); EXPECT_STREQ(sampling_result.tracestate.c_str(), "5b3f9fed-980df25c@dt=fw4;0;0;0;0;0;0;95"); EXPECT_TRUE(sampling_result.isRecording()); EXPECT_TRUE(sampling_result.isSampled()); @@ -94,6 +96,8 @@ TEST_F(DynatraceSamplerTest, TestWithUnknownParentContext) { ::opentelemetry::proto::trace::v1::Span::SPAN_KIND_SERVER, {}, {}); EXPECT_EQ(sampling_result.decision, Decision::RecordAndSample); EXPECT_EQ(sampling_result.attributes->size(), 1); + EXPECT_STREQ( + sampling_result.attributes->find("supportability.atm_sampling_ratio")->second.c_str(), "1"); // Dynatrace tracesate should be prepended EXPECT_STREQ(sampling_result.tracestate.c_str(), "5b3f9fed-980df25c@dt=fw4;0;0;0;0;0;0;95,some_vendor=some_value"); @@ -110,6 +114,8 @@ TEST_F(DynatraceSamplerTest, TestWithDynatraceParentContextSampled) { ::opentelemetry::proto::trace::v1::Span::SPAN_KIND_SERVER, {}, {}); EXPECT_EQ(sampling_result.decision, Decision::RecordAndSample); EXPECT_EQ(sampling_result.attributes->size(), 1); + EXPECT_STREQ( + sampling_result.attributes->find("supportability.atm_sampling_ratio")->second.c_str(), "1"); // tracestate should be forwarded EXPECT_STREQ(sampling_result.tracestate.c_str(), dt_tracestate_sampled); // sampling decision from parent should be respected @@ -126,6 +132,11 @@ TEST_F(DynatraceSamplerTest, TestWithDynatraceParentContextIgnored) { ::opentelemetry::proto::trace::v1::Span::SPAN_KIND_SERVER, {}, {}); EXPECT_EQ(sampling_result.decision, Decision::Drop); EXPECT_EQ(sampling_result.attributes->size(), 1); + EXPECT_EQ(sampling_result.attributes->size(), 2); + EXPECT_STREQ( + sampling_result.attributes->find("supportability.atm_sampling_ratio")->second.c_str(), "4"); + EXPECT_STREQ(sampling_result.attributes->find("sampling.threshold")->second.c_str(), + "54043195528445952"); // tracestate should be forwarded EXPECT_STREQ(sampling_result.tracestate.c_str(), dt_tracestate_ignored); // sampling decision from parent should be respected @@ -144,6 +155,8 @@ TEST_F(DynatraceSamplerTest, TestWithDynatraceParentContextFromDifferentTenant) // sampling decision on tracestate should be ignored because it is from a different tenant. EXPECT_EQ(sampling_result.decision, Decision::RecordAndSample); EXPECT_EQ(sampling_result.attributes->size(), 1); + EXPECT_STREQ( + sampling_result.attributes->find("supportability.atm_sampling_ratio")->second.c_str(), "1"); // new Dynatrace tag should be prepended, already existing tag should be kept const char* exptected = "5b3f9fed-980df25c@dt=fw4;0;0;0;0;0;0;95,6666ad40-980df25c@dt=fw4;4;4af38366;0;0;1;2;123;"