-
Notifications
You must be signed in to change notification settings - Fork 440
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
206 additions
and
1 deletion.
There are no files selected for viewing
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
83 changes: 83 additions & 0 deletions
83
api/include/opentelemetry/trace/propagation/composite_propagator.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,83 @@ | ||
#include <initializer_list> | ||
#include <memory> | ||
#include <vector> | ||
#include "opentelemetry/trace/propagation/text_map_propagator.h" | ||
|
||
OPENTELEMETRY_BEGIN_NAMESPACE | ||
namespace trace | ||
{ | ||
namespace propagation | ||
{ | ||
|
||
template <typename T> | ||
class CompositePropagator : public TextMapPropagator<T> | ||
{ | ||
public: | ||
CompositePropagator(std::vector<std::unique_ptr<TextMapPropagator<T>>> propagators) | ||
: propagators_(std::move(propagators)) | ||
{} | ||
// Rules that manages how context will be extracted from carrier. | ||
using Getter = nostd::string_view (*)(const T &carrier, nostd::string_view trace_type); | ||
|
||
// Rules that manages how context will be injected to carrier. | ||
using Setter = void (*)(T &carrier, | ||
nostd::string_view trace_type, | ||
nostd::string_view trace_description); | ||
|
||
/** | ||
* Run each of the configured propagators with the given context and carrier. | ||
* Propagators are run in the order they are configured, so if multiple | ||
* propagators write the same carrier key, the propagator later in the list | ||
* will "win". | ||
* | ||
* @param setter Rules that manages how context will be injected to carrier. | ||
* @param carrier Carrier into which context will be injected | ||
* @param context Context to inject | ||
* | ||
*/ | ||
|
||
void Inject(Setter setter, T &carrier, const context::Context &context) noexcept override | ||
{ | ||
for (auto &p : propagators_) | ||
{ | ||
p->Inject(setter, carrier, context); | ||
} | ||
} | ||
|
||
/** | ||
* Run each of the configured propagators with the given context and carrier. | ||
* Propagators are run in the order they are configured, so if multiple | ||
* propagators write the same context key, the propagator later in the list | ||
* will "win". | ||
* | ||
* @param setter Rules that manages how context will be extracte from carrier. | ||
* @param context Context to add values to | ||
* @param carrier Carrier from which to extract context | ||
*/ | ||
context::Context Extract(Getter getter, | ||
const T &carrier, | ||
context::Context &context) noexcept override | ||
{ | ||
auto first = true; | ||
context::Context tmp_context; | ||
for (auto &p : propagators_) | ||
{ | ||
if (first) | ||
{ | ||
tmp_context = p->Extract(getter, carrier, context); | ||
first = false; | ||
} | ||
else | ||
{ | ||
tmp_context = p->Extract(getter, carrier, tmp_context); | ||
} | ||
} | ||
return propagators_.size() ? tmp_context : context; | ||
} | ||
|
||
private: | ||
std::vector<std::unique_ptr<TextMapPropagator<T>>> propagators_; | ||
}; | ||
} // namespace propagation | ||
} // namespace trace | ||
OPENTELEMETRY_END_NAMESPACE; |
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
120 changes: 120 additions & 0 deletions
120
api/test/trace/propagation/composite_propagator_test.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,120 @@ | ||
#include "opentelemetry/nostd/string_view.h" | ||
#include "opentelemetry/trace/scope.h" | ||
#include "opentelemetry/trace/span.h" | ||
#include "opentelemetry/trace/span_context.h" | ||
|
||
#include "opentelemetry/trace/default_span.h" | ||
#include "opentelemetry/trace/propagation/b3_propagator.h" | ||
#include "opentelemetry/trace/propagation/composite_propagator.h" | ||
#include "opentelemetry/trace/propagation/http_trace_context.h" | ||
#include "opentelemetry/trace/propagation/text_map_propagator.h" | ||
|
||
#include <map> | ||
#include <memory> | ||
#include <string> | ||
|
||
#include <gtest/gtest.h> | ||
|
||
using namespace opentelemetry; | ||
|
||
template <typename T> | ||
static std::string Hex(const T &id_item) | ||
{ | ||
char buf[T::kSize * 2]; | ||
id_item.ToLowerBase16(buf); | ||
return std::string(buf, sizeof(buf)); | ||
} | ||
|
||
static nostd::string_view Getter(const std::map<std::string, std::string> &carrier, | ||
nostd::string_view trace_type) | ||
{ | ||
auto it = carrier.find(std::string(trace_type)); | ||
if (it != carrier.end()) | ||
{ | ||
return nostd::string_view(it->second); | ||
} | ||
return ""; | ||
} | ||
|
||
static void Setter(std::map<std::string, std::string> &carrier, | ||
nostd::string_view trace_type, | ||
nostd::string_view trace_description = "") | ||
{ | ||
carrier[std::string(trace_type)] = std::string(trace_description); | ||
} | ||
|
||
using MapHttpTraceContext = | ||
trace::propagation::HttpTraceContext<std::map<std::string, std::string>>; | ||
using MapB3Context = trace::propagation::B3Propagator<std::map<std::string, std::string>>; | ||
using MapCompositePropagator = | ||
trace::propagation::CompositePropagator<std::map<std::string, std::string>>; | ||
|
||
class CompositePropagatorTest : public ::testing::Test | ||
{ | ||
using MapHttpTraceContext = | ||
trace::propagation::HttpTraceContext<std::map<std::string, std::string>>; | ||
|
||
using MapB3Context = trace::propagation::B3Propagator<std::map<std::string, std::string>>; | ||
using MapCompositePropagator = | ||
trace::propagation::CompositePropagator<std::map<std::string, std::string>>; | ||
|
||
public: | ||
CompositePropagatorTest() | ||
{ | ||
std::vector< | ||
std::unique_ptr<trace::propagation::TextMapPropagator<std::map<std::string, std::string>>>> | ||
propogator_list = {}; | ||
std::unique_ptr<MapHttpTraceContext> tc_propogator(new MapHttpTraceContext()); | ||
std::unique_ptr<MapB3Context> b3_propogator(new MapB3Context()); | ||
propogator_list.push_back(std::move(tc_propogator)); | ||
propogator_list.push_back(std::move(b3_propogator)); | ||
|
||
composite_propagator_ = new MapCompositePropagator(std::move(propogator_list)); | ||
} | ||
|
||
~CompositePropagatorTest() { delete composite_propagator_; } | ||
|
||
protected: | ||
MapCompositePropagator *composite_propagator_; | ||
}; | ||
|
||
TEST_F(CompositePropagatorTest, Extract) | ||
{ | ||
|
||
const std::map<std::string, std::string> carrier = { | ||
{"traceparent", "00-4bf92f3577b34da6a3ce929d0e0e4736-0102030405060708-01"}, | ||
{"b3", "80f198ee56343ba864fe8b2a57d3eff7-e457b5a2e4d86bd1-1-05e3ac9a4f6e3b90"}}; | ||
context::Context ctx1 = context::Context{}; | ||
|
||
context::Context ctx2 = composite_propagator_->Extract(Getter, carrier, ctx1); | ||
|
||
auto ctx2_span = ctx2.GetValue(trace::kSpanKey); | ||
EXPECT_TRUE(nostd::holds_alternative<nostd::shared_ptr<trace::Span>>(ctx2_span)); | ||
|
||
auto span = nostd::get<nostd::shared_ptr<trace::Span>>(ctx2_span); | ||
|
||
// confirm last propagator in composite propagator list (B3 here) wins for same key | ||
// ("active_span" here). | ||
EXPECT_EQ(Hex(span->GetContext().trace_id()), "80f198ee56343ba864fe8b2a57d3eff7"); | ||
EXPECT_EQ(Hex(span->GetContext().span_id()), "e457b5a2e4d86bd1"); | ||
EXPECT_EQ(span->GetContext().IsSampled(), true); | ||
EXPECT_EQ(span->GetContext().IsRemote(), true); | ||
} | ||
|
||
TEST_F(CompositePropagatorTest, Inject) | ||
{ | ||
|
||
constexpr uint8_t buf_span[] = {1, 2, 3, 4, 5, 6, 7, 8}; | ||
constexpr uint8_t buf_trace[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; | ||
trace::SpanContext span_context{trace::TraceId{buf_trace}, trace::SpanId{buf_span}, | ||
trace::TraceFlags{true}, false}; | ||
nostd::shared_ptr<trace::Span> sp{new trace::DefaultSpan{span_context}}; | ||
|
||
// Set `sp` as the currently active span, which must be used by `Inject`. | ||
trace::Scope scoped_span{sp}; | ||
|
||
std::map<std::string, std::string> headers = {}; | ||
composite_propagator_->Inject(Setter, headers, context::RuntimeContext::GetCurrent()); | ||
EXPECT_EQ(headers["traceparent"], "00-0102030405060708090a0b0c0d0e0f10-0102030405060708-01"); | ||
EXPECT_EQ(headers["b3"], "0102030405060708090a0b0c0d0e0f10-0102030405060708-1"); | ||
} |