Skip to content

Commit

Permalink
add calculateTenantId() to allow to set tenant instead of tenant_id in
Browse files Browse the repository at this point in the history
config file

Signed-off-by: thomas.ebner <[email protected]>
  • Loading branch information
samohte committed Feb 5, 2024
1 parent ecd8336 commit 9f4fd46
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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<const uint8_t*>(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<int>(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)) {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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";

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}

Expand All @@ -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;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;"
Expand All @@ -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";

Expand Down Expand Up @@ -80,23 +80,23 @@ 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());
}

// 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",
::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(),
"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());
}
Expand All @@ -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());
}
Expand Down Expand Up @@ -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());
Expand Down

0 comments on commit 9f4fd46

Please sign in to comment.