From 9f4fd46b456f0fb9d490ff29a3f9dbecbe5e55e7 Mon Sep 17 00:00:00 2001 From: "thomas.ebner" Date: Mon, 5 Feb 2024 11:16:07 +0100 Subject: [PATCH] add calculateTenantId() to allow to set tenant instead of tenant_id in config file Signed-off-by: thomas.ebner --- .../samplers/dynatrace/dynatrace_sampler.cc | 27 ++++++++++++++++++- .../dynatrace_sampler_integration_test.cc | 8 +++--- .../dynatrace/dynatrace_sampler_test.cc | 16 +++++------ 3 files changed, 38 insertions(+), 13 deletions(-) diff --git a/source/extensions/tracers/opentelemetry/samplers/dynatrace/dynatrace_sampler.cc b/source/extensions/tracers/opentelemetry/samplers/dynatrace/dynatrace_sampler.cc index 4776623ed1dc..d74256b0ad38 100644 --- a/source/extensions/tracers/opentelemetry/samplers/dynatrace/dynatrace_sampler.cc +++ b/source/extensions/tracers/opentelemetry/samplers/dynatrace/dynatrace_sampler.cc @@ -11,6 +11,7 @@ #include "source/extensions/tracers/opentelemetry/trace_state.h" #include "absl/strings/str_cat.h" +#include "openssl/md5.h" namespace Envoy { namespace Extensions { @@ -22,13 +23,37 @@ namespace { constexpr std::chrono::minutes SAMPLING_UPDATE_TIMER_DURATION{1}; const char* SAMPLING_EXTRAPOLATION_SPAN_ATTRIBUTE_NAME = "sampling_extrapolation_set_in_sampler"; +absl::Hex calculateTenantId(std::string tenant_uuid) { + if (tenant_uuid.empty()) { + return absl::Hex(0); + } + + for (char& c : tenant_uuid) { + if (c & 0x80) { + c = 0x3f; // '?' + } + } + + uint8_t digest[16]; + MD5(reinterpret_cast(tenant_uuid.data()), tenant_uuid.size(), digest); + + int32_t hash = 0; + for (int i = 0; i < 16; i++) { + const int shift_for_target_byte = (3 - (i % 4)) * 8; + // 24, 16, 8, 0 respectively + hash ^= + (static_cast(digest[i]) << shift_for_target_byte) & (0xff << shift_for_target_byte); + } + return absl::Hex(hash); +} + } // namespace DynatraceSampler::DynatraceSampler( const envoy::extensions::tracers::opentelemetry::samplers::v3::DynatraceSamplerConfig& config, Server::Configuration::TracerFactoryContext& context, SamplerConfigFetcherPtr sampler_config_fetcher) - : dt_tracestate_key_(absl::StrCat(absl::string_view(config.tenant_id()), "-", + : dt_tracestate_key_(absl::StrCat(calculateTenantId(config.tenant_id()), "-", absl::string_view(config.cluster_id()), "@dt")), sampling_controller_(std::move(sampler_config_fetcher)) { diff --git a/test/extensions/tracers/opentelemetry/samplers/dynatrace/dynatrace_sampler_integration_test.cc b/test/extensions/tracers/opentelemetry/samplers/dynatrace/dynatrace_sampler_integration_test.cc index 9d9d20b42283..7664e50e1dbc 100644 --- a/test/extensions/tracers/opentelemetry/samplers/dynatrace/dynatrace_sampler_integration_test.cc +++ b/test/extensions/tracers/opentelemetry/samplers/dynatrace/dynatrace_sampler_integration_test.cc @@ -37,7 +37,7 @@ class DynatraceSamplerIntegrationTest : public Envoy::HttpIntegrationTest, name: envoy.tracers.opentelemetry.samplers.dynatrace typed_config: "@type": type.googleapis.com/envoy.extensions.tracers.opentelemetry.samplers.v3.DynatraceSamplerConfig - tenant_id: "9712ad40" + tenant_id: "abc12345" cluster_id: "980df25c" )EOF"; @@ -83,7 +83,7 @@ TEST_P(DynatraceSamplerIntegrationTest, TestWithTraceparentAndTracestate) { ->value() .getStringView(); // use StartsWith because pathinfo (last element in trace state contains a random value) - EXPECT_TRUE(absl::StartsWith(tracestate_value, "9712ad40-980df25c@dt=fw4;0;0;0;0;0;0;")) + EXPECT_TRUE(absl::StartsWith(tracestate_value, "5b3f9fed-980df25c@dt=fw4;0;0;0;0;0;0;")) << "Received tracestate: " << tracestate_value; EXPECT_TRUE(absl::StrContains(tracestate_value, ",key=value")) << "Received tracestate: " << tracestate_value; @@ -115,7 +115,7 @@ TEST_P(DynatraceSamplerIntegrationTest, TestWithTraceparentOnly) { ->value() .getStringView(); // use StartsWith because pathinfo (last element in trace state contains a random value) - EXPECT_TRUE(absl::StartsWith(tracestate_value, "9712ad40-980df25c@dt=fw4;0;0;0;0;0;0;")) + EXPECT_TRUE(absl::StartsWith(tracestate_value, "5b3f9fed-980df25c@dt=fw4;0;0;0;0;0;0;")) << "Received tracestate: " << tracestate_value; } @@ -139,7 +139,7 @@ TEST_P(DynatraceSamplerIntegrationTest, TestWithoutTraceparentAndTracestate) { .get(Http::LowerCaseString("tracestate"))[0] ->value() .getStringView(); - EXPECT_TRUE(absl::StartsWith(tracestate_value, "9712ad40-980df25c@dt=fw4;0;0;0;0;0;0;")) + EXPECT_TRUE(absl::StartsWith(tracestate_value, "5b3f9fed-980df25c@dt=fw4;0;0;0;0;0;0;")) << "Received tracestate: " << tracestate_value; } 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 1748d353d49f..29982fc594b7 100644 --- a/test/extensions/tracers/opentelemetry/samplers/dynatrace/dynatrace_sampler_test.cc +++ b/test/extensions/tracers/opentelemetry/samplers/dynatrace/dynatrace_sampler_test.cc @@ -23,10 +23,10 @@ const char* trace_id = "67a9a23155e1741b5b35368e08e6ece5"; const char* parent_span_id = "9d83def9a4939b7b"; const char* dt_tracestate_ignored = - "9712ad40-980df25c@dt=fw4;4;4af38366;0;0;1;2;123;8eae;2h01;3h4af38366;4h00;5h01;" + "5b3f9fed-980df25c@dt=fw4;4;4af38366;0;0;1;2;123;8eae;2h01;3h4af38366;4h00;5h01;" "6h67a9a23155e1741b5b35368e08e6ece5;7h9d83def9a4939b7b"; const char* dt_tracestate_sampled = - "9712ad40-980df25c@dt=fw4;4;4af38366;0;0;0;0;123;8eae;2h01;3h4af38366;4h00;5h01;" + "5b3f9fed-980df25c@dt=fw4;4;4af38366;0;0;0;0;123;8eae;2h01;3h4af38366;4h00;5h01;" "6h67a9a23155e1741b5b35368e08e6ece5;7h9d83def9a4939b7b"; const char* dt_tracestate_ignored_different_tenant = "6666ad40-980df25c@dt=fw4;4;4af38366;0;0;1;2;123;8eae;2h01;3h4af38366;4h00;5h01;" @@ -42,7 +42,7 @@ class MockSamplerConfigFetcher : public SamplerConfigFetcher { class DynatraceSamplerTest : public testing::Test { const std::string yaml_string_ = R"EOF( - tenant_id: "9712ad40" + tenant_id: "abc12345" cluster_id: "980df25c" )EOF"; @@ -80,7 +80,7 @@ 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.tracestate.c_str(), "9712ad40-980df25c@dt=fw4;0;0;0;0;0;0;95"); + 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()); } @@ -88,7 +88,7 @@ TEST_F(DynatraceSamplerTest, TestWithoutParentContext) { // Verify sampler being invoked with existing Dynatrace trace state tag set TEST_F(DynatraceSamplerTest, TestWithParentContext) { SpanContext parent_context = SpanContext("00", trace_id, "b7ad6b7169203331", true, - "ot=foo:bar,9712ad40-980df25c@dt=fw4;0;0;0;0;0;0;ad"); + "ot=foo:bar,5b3f9fed-980df25c@dt=fw4;0;0;0;0;0;0;ad"); SamplingResult sampling_result = sampler_->shouldSample(parent_context, trace_id, "parent_span", @@ -96,7 +96,7 @@ TEST_F(DynatraceSamplerTest, TestWithParentContext) { EXPECT_EQ(sampling_result.decision, Decision::RecordAndSample); EXPECT_EQ(sampling_result.attributes->size(), 1); EXPECT_STREQ(sampling_result.tracestate.c_str(), - "ot=foo:bar,9712ad40-980df25c@dt=fw4;0;0;0;0;0;0;ad"); + "ot=foo:bar,5b3f9fed-980df25c@dt=fw4;0;0;0;0;0;0;ad"); EXPECT_TRUE(sampling_result.isRecording()); EXPECT_TRUE(sampling_result.isSampled()); } @@ -111,7 +111,7 @@ TEST_F(DynatraceSamplerTest, TestWithUnknownParentContext) { EXPECT_EQ(sampling_result.decision, Decision::RecordAndSample); EXPECT_EQ(sampling_result.attributes->size(), 1); EXPECT_STREQ(sampling_result.tracestate.c_str(), - "9712ad40-980df25c@dt=fw4;0;0;0;0;0;0;95,some_vendor=some_value"); + "5b3f9fed-980df25c@dt=fw4;0;0;0;0;0;0;95,some_vendor=some_value"); EXPECT_TRUE(sampling_result.isRecording()); EXPECT_TRUE(sampling_result.isSampled()); } @@ -156,7 +156,7 @@ TEST_F(DynatraceSamplerTest, TestWithDynatraceParentContextFromDifferentTenant) EXPECT_EQ(sampling_result.decision, Decision::RecordAndSample); EXPECT_EQ(sampling_result.attributes->size(), 1); const char* exptected = - "9712ad40-980df25c@dt=fw4;0;0;0;0;0;0;95,6666ad40-980df25c@dt=fw4;4;4af38366;0;0;1;2;123;" + "5b3f9fed-980df25c@dt=fw4;0;0;0;0;0;0;95,6666ad40-980df25c@dt=fw4;4;4af38366;0;0;1;2;123;" "8eae;2h01;3h4af38366;4h00;5h01;6h67a9a23155e1741b5b35368e08e6ece5;7h9d83def9a4939b7b"; EXPECT_STREQ(sampling_result.tracestate.c_str(), exptected); EXPECT_TRUE(sampling_result.isRecording());