forked from envoyproxy/envoy
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Feat/dynatrace sampler internal (#11)
Signed-off-by: thomas.ebner <[email protected]> Signed-off-by: Joao Grassi <[email protected]>
- Loading branch information
1 parent
c82c083
commit f1fddbc
Showing
18 changed files
with
912 additions
and
0 deletions.
There are no files selected for viewing
20 changes: 20 additions & 0 deletions
20
api/envoy/extensions/tracers/opentelemetry/samplers/v3/dynatrace_sampler.proto
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
syntax = "proto3"; | ||
|
||
package envoy.extensions.tracers.opentelemetry.samplers.v3; | ||
|
||
import "udpa/annotations/status.proto"; | ||
|
||
option java_package = "io.envoyproxy.envoy.extensions.tracers.opentelemetry.samplers.v3"; | ||
option java_outer_classname = "DynatraceSamplerProto"; | ||
option java_multiple_files = true; | ||
option go_package = "github.com/envoyproxy/go-control-plane/envoy/extensions/tracers/opentelemetry/samplers/v3;samplersv3"; | ||
option (udpa.annotations.file_status).package_version_status = ACTIVE; | ||
|
||
// [#protodoc-title: Dynatrace Sampler config] | ||
// [#extension: envoy.tracers.opentelemetry.samplers.dynatrace] | ||
|
||
message DynatraceSamplerConfig { | ||
string tenant_id = 1; | ||
|
||
string cluster_id = 2; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
42 changes: 42 additions & 0 deletions
42
source/extensions/tracers/opentelemetry/samplers/dynatrace/BUILD
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
load( | ||
"//bazel:envoy_build_system.bzl", | ||
"envoy_cc_extension", | ||
"envoy_cc_library", | ||
"envoy_extension_package", | ||
) | ||
|
||
licenses(["notice"]) # Apache 2 | ||
|
||
envoy_extension_package() | ||
|
||
envoy_cc_extension( | ||
name = "config", | ||
srcs = ["config.cc"], | ||
hdrs = ["config.h"], | ||
deps = [ | ||
":dynatrace_sampler_lib", | ||
"//envoy/registry", | ||
"//source/common/config:utility_lib", | ||
"@envoy_api//envoy/extensions/tracers/opentelemetry/samplers/v3:pkg_cc_proto", | ||
], | ||
) | ||
|
||
envoy_cc_library( | ||
name = "dynatrace_sampler_lib", | ||
srcs = [ | ||
"dynatrace_sampler.cc", | ||
"dynatrace_tracestate.cc", | ||
"tracestate.cc", | ||
], | ||
hdrs = [ | ||
"dynatrace_sampler.h", | ||
"dynatrace_tracestate.h", | ||
"tracestate.h", | ||
], | ||
deps = [ | ||
"//source/common/config:datasource_lib", | ||
"//source/extensions/tracers/opentelemetry:opentelemetry_tracer_lib", | ||
"//source/extensions/tracers/opentelemetry/samplers:sampler_lib", | ||
"@envoy_api//envoy/extensions/tracers/opentelemetry/samplers/v3:pkg_cc_proto", | ||
], | ||
) |
34 changes: 34 additions & 0 deletions
34
source/extensions/tracers/opentelemetry/samplers/dynatrace/config.cc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
#include "config.h" | ||
|
||
#include "envoy/extensions/tracers/opentelemetry/samplers/v3/dynatrace_sampler.pb.validate.h" | ||
|
||
#include "source/common/config/utility.h" | ||
#include "source/common/protobuf/utility.h" | ||
#include "source/extensions/tracers/opentelemetry/samplers/dynatrace/dynatrace_sampler.h" | ||
|
||
namespace Envoy { | ||
namespace Extensions { | ||
namespace Tracers { | ||
namespace OpenTelemetry { | ||
|
||
SamplerSharedPtr | ||
DynatraceSamplerFactory::createSampler(const Protobuf::Message& config, | ||
Server::Configuration::TracerFactoryContext& context) { | ||
auto mptr = Envoy::Config::Utility::translateAnyToFactoryConfig( | ||
dynamic_cast<const ProtobufWkt::Any&>(config), context.messageValidationVisitor(), *this); | ||
return std::make_shared<DynatraceSampler>( | ||
MessageUtil::downcastAndValidate< | ||
const envoy::extensions::tracers::opentelemetry::samplers::v3::DynatraceSamplerConfig&>( | ||
*mptr, context.messageValidationVisitor()), | ||
context); | ||
} | ||
|
||
/** | ||
* Static registration for the Env sampler factory. @see RegisterFactory. | ||
*/ | ||
REGISTER_FACTORY(DynatraceSamplerFactory, SamplerFactory); | ||
|
||
} // namespace OpenTelemetry | ||
} // namespace Tracers | ||
} // namespace Extensions | ||
} // namespace Envoy |
41 changes: 41 additions & 0 deletions
41
source/extensions/tracers/opentelemetry/samplers/dynatrace/config.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
#pragma once | ||
|
||
#include <string> | ||
|
||
#include "envoy/extensions/tracers/opentelemetry/samplers/v3/dynatrace_sampler.pb.h" | ||
#include "envoy/registry/registry.h" | ||
|
||
#include "source/extensions/tracers/opentelemetry/samplers/sampler.h" | ||
|
||
namespace Envoy { | ||
namespace Extensions { | ||
namespace Tracers { | ||
namespace OpenTelemetry { | ||
|
||
/** | ||
* Config registration for the DynatraceSampler. @see SamplerFactory. | ||
*/ | ||
class DynatraceSamplerFactory : public SamplerFactory { | ||
public: | ||
/** | ||
* @brief Create a Sampler which samples every span | ||
* | ||
* @param context | ||
* @return SamplerSharedPtr | ||
*/ | ||
SamplerSharedPtr createSampler(const Protobuf::Message& config, | ||
Server::Configuration::TracerFactoryContext& context) override; | ||
|
||
ProtobufTypes::MessagePtr createEmptyConfigProto() override { | ||
return std::make_unique< | ||
envoy::extensions::tracers::opentelemetry::samplers::v3::DynatraceSamplerConfig>(); | ||
} | ||
std::string name() const override { return "envoy.tracers.opentelemetry.samplers.dynatrace"; } | ||
}; | ||
|
||
DECLARE_FACTORY(DynatraceSamplerFactory); | ||
|
||
} // namespace OpenTelemetry | ||
} // namespace Tracers | ||
} // namespace Extensions | ||
} // namespace Envoy |
88 changes: 88 additions & 0 deletions
88
source/extensions/tracers/opentelemetry/samplers/dynatrace/dynatrace_sampler.cc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
#include "source/extensions/tracers/opentelemetry/samplers/dynatrace/dynatrace_sampler.h" | ||
|
||
#include <memory> | ||
#include <sstream> | ||
#include <string> | ||
|
||
#include "source/common/config/datasource.h" | ||
#include "source/extensions/tracers/opentelemetry/samplers/dynatrace/dynatrace_tracestate.h" | ||
#include "source/extensions/tracers/opentelemetry/samplers/dynatrace/tracestate.h" | ||
#include "source/extensions/tracers/opentelemetry/samplers/sampler.h" | ||
#include "source/extensions/tracers/opentelemetry/span_context.h" | ||
|
||
namespace Envoy { | ||
namespace Extensions { | ||
namespace Tracers { | ||
namespace OpenTelemetry { | ||
|
||
static const char* SAMPLING_EXTRAPOLATION_SPAN_ATTRIBUTE_NAME = | ||
"sampling_extrapolation_set_in_sampler"; | ||
|
||
FW4Tag DynatraceSampler::getFW4Tag(const Tracestate& tracestate) { | ||
for (auto const& entry : tracestate.entries()) { | ||
if (dt_tracestate_entry_.keyMatches( | ||
entry.key)) { // found a tracestate entry with key matching our tenant/cluster | ||
return FW4Tag::create(entry.value); | ||
} | ||
} | ||
return FW4Tag::createInvalid(); | ||
} | ||
|
||
DynatraceSampler::DynatraceSampler( | ||
const envoy::extensions::tracers::opentelemetry::samplers::v3::DynatraceSamplerConfig& config, | ||
Server::Configuration::TracerFactoryContext& /*context*/) | ||
: tenant_id_(config.tenant_id()), cluster_id_(config.cluster_id()), | ||
dt_tracestate_entry_(tenant_id_, cluster_id_), counter_(0) {} | ||
|
||
SamplingResult DynatraceSampler::shouldSample(const absl::optional<SpanContext> parent_context, | ||
const std::string& /*trace_id*/, | ||
const std::string& /*name*/, OTelSpanKind /*kind*/, | ||
OptRef<const Tracing::TraceContext> /*trace_context*/, | ||
const std::vector<SpanContext>& /*links*/) { | ||
|
||
SamplingResult result; | ||
std::map<std::string, std::string> att; | ||
// search for an existing forward tag in the tracestate | ||
Tracestate tracestate; | ||
tracestate.parse(parent_context.has_value() ? parent_context->tracestate() : ""); | ||
|
||
if (FW4Tag fw4_tag = getFW4Tag(tracestate); | ||
fw4_tag.isValid()) { // we found a trace decision in tracestate header | ||
result.decision = fw4_tag.isIgnored() ? Decision::DROP : Decision::RECORD_AND_SAMPLE; | ||
att[SAMPLING_EXTRAPOLATION_SPAN_ATTRIBUTE_NAME] = std::to_string(fw4_tag.getSamplingExponent()); | ||
result.tracestate = parent_context->tracestate(); | ||
|
||
} else { // make a sampling decision | ||
// this is just a demo, we sample every second request here | ||
uint32_t current_counter = ++counter_; | ||
bool sample; | ||
int sampling_exponent; | ||
if (current_counter % 2) { | ||
sample = true; | ||
sampling_exponent = 1; | ||
} else { | ||
sample = false; | ||
sampling_exponent = 0; | ||
} | ||
|
||
att[SAMPLING_EXTRAPOLATION_SPAN_ATTRIBUTE_NAME] = std::to_string(sampling_exponent); | ||
|
||
result.decision = sample ? Decision::RECORD_AND_SAMPLE : Decision::DROP; | ||
// create new forward tag and add it to tracestate | ||
FW4Tag new_tag = FW4Tag::create(!sample, sampling_exponent); | ||
tracestate.add(dt_tracestate_entry_.getKey(), new_tag.asString()); | ||
result.tracestate = tracestate.asString(); | ||
} | ||
|
||
if (!att.empty()) { | ||
result.attributes = std::make_unique<const std::map<std::string, std::string>>(std::move(att)); | ||
} | ||
return result; | ||
} | ||
|
||
std::string DynatraceSampler::getDescription() const { return "DynatraceSampler"; } | ||
|
||
} // namespace OpenTelemetry | ||
} // namespace Tracers | ||
} // namespace Extensions | ||
} // namespace Envoy |
45 changes: 45 additions & 0 deletions
45
source/extensions/tracers/opentelemetry/samplers/dynatrace/dynatrace_sampler.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
#pragma once | ||
|
||
#include "envoy/extensions/tracers/opentelemetry/samplers/v3/dynatrace_sampler.pb.h" | ||
#include "envoy/server/factory_context.h" | ||
|
||
#include "source/common/common/logger.h" | ||
#include "source/common/config/datasource.h" | ||
#include "source/extensions/tracers/opentelemetry/samplers/dynatrace/dynatrace_tracestate.h" | ||
#include "source/extensions/tracers/opentelemetry/samplers/dynatrace/tracestate.h" | ||
#include "source/extensions/tracers/opentelemetry/samplers/sampler.h" | ||
|
||
namespace Envoy { | ||
namespace Extensions { | ||
namespace Tracers { | ||
namespace OpenTelemetry { | ||
|
||
/** | ||
* @brief A Dynatrace specific sampler * | ||
*/ | ||
class DynatraceSampler : public Sampler, Logger::Loggable<Logger::Id::tracing> { | ||
public: | ||
DynatraceSampler( | ||
const envoy::extensions::tracers::opentelemetry::samplers::v3::DynatraceSamplerConfig& config, | ||
Server::Configuration::TracerFactoryContext& context); | ||
|
||
SamplingResult shouldSample(const absl::optional<SpanContext> parent_context, | ||
const std::string& trace_id, const std::string& name, | ||
OTelSpanKind spankind, | ||
OptRef<const Tracing::TraceContext> trace_context, | ||
const std::vector<SpanContext>& links) override; | ||
|
||
std::string getDescription() const override; | ||
|
||
private: | ||
std::string tenant_id_; | ||
std::string cluster_id_; | ||
DtTracestateEntry dt_tracestate_entry_; | ||
std::atomic<uint32_t> counter_; // request counter for dummy sampling | ||
FW4Tag getFW4Tag(const Tracestate& tracestate); | ||
}; | ||
|
||
} // namespace OpenTelemetry | ||
} // namespace Tracers | ||
} // namespace Extensions | ||
} // namespace Envoy |
46 changes: 46 additions & 0 deletions
46
source/extensions/tracers/opentelemetry/samplers/dynatrace/dynatrace_tracestate.cc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
#include "source/extensions/tracers/opentelemetry/samplers/dynatrace/dynatrace_tracestate.h" | ||
|
||
#include <string> | ||
#include <vector> | ||
|
||
#include "absl/strings/match.h" | ||
#include "absl/strings/str_cat.h" | ||
#include "absl/strings/str_split.h" | ||
#include "absl/strings/string_view.h" | ||
|
||
namespace Envoy { | ||
namespace Extensions { | ||
namespace Tracers { | ||
namespace OpenTelemetry { | ||
|
||
FW4Tag FW4Tag::createInvalid() { return {false, false, 0}; } | ||
|
||
FW4Tag FW4Tag::create(bool ignored, int sampling_exponent) { | ||
return {true, ignored, sampling_exponent}; | ||
} | ||
|
||
FW4Tag FW4Tag::create(const std::string& value) { | ||
std::vector<absl::string_view> tracestate_components = | ||
absl::StrSplit(value, ';', absl::AllowEmpty()); | ||
if (tracestate_components.size() < 7) { | ||
return createInvalid(); | ||
} | ||
|
||
if (tracestate_components[0] != "fw4") { | ||
return createInvalid(); | ||
} | ||
bool ignored = tracestate_components[5] == "1"; | ||
int sampling_exponent = std::stoi(std::string(tracestate_components[6])); | ||
return {true, ignored, sampling_exponent}; | ||
} | ||
|
||
std::string FW4Tag::asString() const { | ||
std::string ret = | ||
absl::StrCat("fw4;0;0;0;0;", ignored_ ? "1" : "0", ";", sampling_exponent_, ";0"); | ||
return ret; | ||
} | ||
|
||
} // namespace OpenTelemetry | ||
} // namespace Tracers | ||
} // namespace Extensions | ||
} // namespace Envoy |
53 changes: 53 additions & 0 deletions
53
source/extensions/tracers/opentelemetry/samplers/dynatrace/dynatrace_tracestate.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
#pragma once | ||
|
||
#include <string> | ||
|
||
#include "absl/strings/str_cat.h" | ||
#include "absl/strings/string_view.h" | ||
|
||
namespace Envoy { | ||
namespace Extensions { | ||
namespace Tracers { | ||
namespace OpenTelemetry { | ||
|
||
class FW4Tag { | ||
public: | ||
static FW4Tag createInvalid(); | ||
|
||
static FW4Tag create(bool ignored, int sampling_exponent); | ||
|
||
static FW4Tag create(const std::string& value); | ||
|
||
std::string asString() const; | ||
|
||
bool isValid() const { return valid_; }; | ||
bool isIgnored() const { return ignored_; }; | ||
int getSamplingExponent() const { return sampling_exponent_; }; | ||
|
||
private: | ||
FW4Tag(bool valid, bool ignored, int sampling_exponent) | ||
: valid_(valid), ignored_(ignored), sampling_exponent_(sampling_exponent) {} | ||
|
||
bool valid_; | ||
bool ignored_; | ||
int sampling_exponent_; | ||
}; | ||
|
||
// <tenantID>-<clusterID>@dt=fw4;0;0;0;0;<isIgnored>;<sampling_exponent>;<rootPathRandom> | ||
class DtTracestateEntry { | ||
public: | ||
DtTracestateEntry(const std::string& tenant_id, const std::string& cluster_id) { | ||
key_ = absl::StrCat(absl::string_view(tenant_id), "-", absl::string_view(cluster_id), "@dt"); | ||
} | ||
|
||
std::string getKey() const { return key_; }; | ||
|
||
bool keyMatches(const std::string& key) { return (key_.compare(key) == 0); } | ||
|
||
private: | ||
std::string key_; | ||
}; | ||
} // namespace OpenTelemetry | ||
} // namespace Tracers | ||
} // namespace Extensions | ||
} // namespace Envoy |
Oops, something went wrong.