Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Non-template propagator, Implement Global Propagator, no-op propagator #668

Merged
merged 12 commits into from
Apr 23, 2021
50 changes: 18 additions & 32 deletions api/include/opentelemetry/trace/propagation/b3_propagator.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,19 +37,15 @@ static const int kSpanIdHexStrLength = 16;
// headers of HTTP requests. HTTP frameworks and clients can integrate with B3Propagator by
// providing the object containing the headers, and a getter function for the extraction. Based on:
// https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/context/api-propagators.md#b3-extract
template <typename T>
class B3PropagatorExtractor : public TextMapPropagator<T>

class B3PropagatorExtractor : public TextMapPropagator
{
public:
// Rules that manages how context will be extracted from carrier.
using Getter = nostd::string_view (*)(const T &carrier, nostd::string_view trace_type);

// Returns the context that is stored in the HTTP header carrier with the getter as extractor.
context::Context Extract(Getter getter,
const T &carrier,
// Returns the context that is stored in the HTTP header carrier.
context::Context Extract(const TextMapCarrier &carrier,
context::Context &context) noexcept override
{
SpanContext span_context = ExtractImpl(getter, carrier);
SpanContext span_context = ExtractImpl(carrier);
nostd::shared_ptr<Span> sp{new DefaultSpan(span_context)};
return context.SetValue(kSpanKey, sp);
}
Expand Down Expand Up @@ -78,14 +74,14 @@ class B3PropagatorExtractor : public TextMapPropagator<T>
}

private:
static SpanContext ExtractImpl(Getter getter, const T &carrier)
static SpanContext ExtractImpl(const TextMapCarrier &carrier)
{
nostd::string_view trace_id_hex;
nostd::string_view span_id_hex;
nostd::string_view trace_flags_hex;

// first let's try a single-header variant
auto singleB3Header = getter(carrier, kB3CombinedHeader);
auto singleB3Header = carrier.Get(kB3CombinedHeader);
if (!singleB3Header.empty())
{
std::array<nostd::string_view, 3> fields{};
Expand All @@ -101,9 +97,9 @@ class B3PropagatorExtractor : public TextMapPropagator<T>
}
else
{
trace_id_hex = getter(carrier, kB3TraceIdHeader);
span_id_hex = getter(carrier, kB3SpanIdHeader);
trace_flags_hex = getter(carrier, kB3SampledHeader);
trace_id_hex = carrier.Get(kB3TraceIdHeader);
span_id_hex = carrier.Get(kB3SpanIdHeader);
trace_flags_hex = carrier.Get(kB3SampledHeader);
}

if (!detail::IsValidHex(trace_id_hex) || !detail::IsValidHex(span_id_hex))
Expand All @@ -125,16 +121,11 @@ class B3PropagatorExtractor : public TextMapPropagator<T>

// The B3Propagator class provides interface that enables extracting and injecting context into
// single header of HTTP Request.
template <typename T>
class B3Propagator : public B3PropagatorExtractor<T>
class B3Propagator : public B3PropagatorExtractor
{
public:
// 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);
// Sets the context for a HTTP header carrier with self defined rules.
void Inject(Setter setter, T &carrier, const context::Context &context) noexcept override
void Inject(TextMapCarrier &carrier, const context::Context &context) noexcept override
{
SpanContext span_context = detail::GetCurrentSpan(context);
if (!span_context.IsValid())
Expand All @@ -152,19 +143,14 @@ class B3Propagator : public B3PropagatorExtractor<T>
trace_identity[kTraceIdHexStrLength + kSpanIdHexStrLength + 2] =
span_context.trace_flags().IsSampled() ? '1' : '0';

setter(carrier, kB3CombinedHeader, nostd::string_view(trace_identity, sizeof(trace_identity)));
carrier.Set(kB3CombinedHeader, nostd::string_view(trace_identity, sizeof(trace_identity)));
}
};

template <typename T>
class B3PropagatorMultiHeader : public B3PropagatorExtractor<T>
class B3PropagatorMultiHeader : public B3PropagatorExtractor
{
public:
// 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);
void Inject(Setter setter, T &carrier, const context::Context &context) noexcept override
void Inject(TextMapCarrier &carrier, const context::Context &context) noexcept override
{
SpanContext span_context = detail::GetCurrentSpan(context);
if (!span_context.IsValid())
Expand All @@ -177,9 +163,9 @@ class B3PropagatorMultiHeader : public B3PropagatorExtractor<T>
SpanId(span_context.span_id()).ToLowerBase16(span_id);
char trace_flags[2];
TraceFlags(span_context.trace_flags()).ToLowerBase16(trace_flags);
setter(carrier, kB3TraceIdHeader, nostd::string_view(trace_id, sizeof(trace_id)));
setter(carrier, kB3SpanIdHeader, nostd::string_view(span_id, sizeof(span_id)));
setter(carrier, kB3SampledHeader, nostd::string_view(trace_flags + 1, 1));
carrier.Set(kB3TraceIdHeader, nostd::string_view(trace_id, sizeof(trace_id)));
carrier.Set(kB3SpanIdHeader, nostd::string_view(span_id, sizeof(span_id)));
carrier.Set(kB3SampledHeader, nostd::string_view(trace_flags + 1, 1));
}
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,38 +9,29 @@ namespace trace
namespace propagation
{

template <typename T>
class CompositePropagator : public TextMapPropagator<T>
class CompositePropagator : public TextMapPropagator
{
public:
CompositePropagator(std::vector<std::unique_ptr<TextMapPropagator<T>>> propagators)
CompositePropagator(std::vector<std::unique_ptr<TextMapPropagator>> 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
void Inject(TextMapCarrier &carrier, const context::Context &context) noexcept override
{
for (auto &p : propagators_)
{
p->Inject(setter, carrier, context);
p->Inject(carrier, context);
}
}

Expand All @@ -50,12 +41,10 @@ class CompositePropagator : public TextMapPropagator<T>
* 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
* @param context Context to add values to
*/
context::Context Extract(Getter getter,
const T &carrier,
context::Context Extract(const TextMapCarrier &carrier,
context::Context &context) noexcept override
{
auto first = true;
Expand All @@ -64,19 +53,19 @@ class CompositePropagator : public TextMapPropagator<T>
{
if (first)
{
tmp_context = p->Extract(getter, carrier, context);
tmp_context = p->Extract(carrier, context);
first = false;
}
else
{
tmp_context = p->Extract(getter, carrier, tmp_context);
tmp_context = p->Extract(carrier, tmp_context);
}
}
return propagators_.size() ? tmp_context : context;
}

private:
std::vector<std::unique_ptr<TextMapPropagator<T>>> propagators_;
std::vector<std::unique_ptr<TextMapPropagator>> propagators_;
};
} // namespace propagation
} // namespace trace
Expand Down
66 changes: 66 additions & 0 deletions api/include/opentelemetry/trace/propagation/global_propagator.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// Copyright 2021, OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#pragma once
lalitb marked this conversation as resolved.
Show resolved Hide resolved

#include <mutex>

#include "opentelemetry/trace/propagation/noop_propagator.h"
#include "opentelemetry/trace/propagation/text_map_propagator.h"

#include "opentelemetry/common/spin_lock_mutex.h"
#include "opentelemetry/nostd/shared_ptr.h"

#include "opentelemetry/version.h"

OPENTELEMETRY_BEGIN_NAMESPACE
namespace trace
{
namespace propagation
{

/* Stores the singleton TextMapPropagator */

class GlobalTextMapPropagator
{
public:
static nostd::shared_ptr<TextMapPropagator> GetGlobalPropagator() noexcept
{
std::lock_guard<common::SpinLockMutex> guard(GetLock());
return nostd::shared_ptr<TextMapPropagator>(GetPropagator());
}

static void SetGlobalPropagator(nostd::shared_ptr<TextMapPropagator> prop) noexcept
{
std::lock_guard<common::SpinLockMutex> guard(GetLock());
GetPropagator() = prop;
}

private:
static nostd::shared_ptr<TextMapPropagator> &GetPropagator() noexcept
{
static nostd::shared_ptr<TextMapPropagator> propagator(new NoOpPropagator());
return propagator;
}

static common::SpinLockMutex &GetLock() noexcept
{
static common::SpinLockMutex lock;
return lock;
}
};

} // namespace propagation
} // namespace trace
OPENTELEMETRY_END_NAMESPACE
33 changes: 12 additions & 21 deletions api/include/opentelemetry/trace/propagation/http_trace_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,33 +36,24 @@ static const size_t kTraceParentSize = 55;
// Example:
// HttpTraceContext().inject(setter, carrier, context);
// HttpTraceContext().extract(getter, carrier, context);
template <typename T>
class HttpTraceContext : public TextMapPropagator<T>

class HttpTraceContext : public TextMapPropagator
{
public:
// 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);

void Inject(Setter setter, T &carrier, const context::Context &context) noexcept override
void Inject(TextMapCarrier &carrier, const context::Context &context) noexcept override
{
SpanContext span_context = detail::GetCurrentSpan(context);
if (!span_context.IsValid())
{
return;
}
InjectImpl(setter, carrier, span_context);
InjectImpl(carrier, span_context);
}

context::Context Extract(Getter getter,
const T &carrier,
context::Context Extract(const TextMapCarrier &carrier,
context::Context &context) noexcept override
{
SpanContext span_context = ExtractImpl(getter, carrier);
SpanContext span_context = ExtractImpl(carrier);
nostd::shared_ptr<Span> sp{new DefaultSpan(span_context)};
return context.SetValue(kSpanKey, sp);
}
Expand Down Expand Up @@ -98,7 +89,7 @@ class HttpTraceContext : public TextMapPropagator<T>
return version != kInvalidVersion;
}

static void InjectImpl(Setter setter, T &carrier, const SpanContext &span_context)
static void InjectImpl(TextMapCarrier &carrier, const SpanContext &span_context)
{
char trace_parent[kTraceParentSize];
trace_parent[0] = '0';
Expand All @@ -110,8 +101,8 @@ class HttpTraceContext : public TextMapPropagator<T>
trace_parent[kTraceIdSize + kSpanIdSize + 4] = '-';
span_context.trace_flags().ToLowerBase16({&trace_parent[kTraceIdSize + kSpanIdSize + 5], 2});

setter(carrier, kTraceParent, nostd::string_view(trace_parent, sizeof(trace_parent)));
setter(carrier, kTraceState, span_context.trace_state()->ToHeader());
carrier.Set(kTraceParent, nostd::string_view(trace_parent, sizeof(trace_parent)));
carrier.Set(kTraceState, span_context.trace_state()->ToHeader());
}

static SpanContext ExtractContextFromTraceHeaders(nostd::string_view trace_parent,
Expand Down Expand Up @@ -162,10 +153,10 @@ class HttpTraceContext : public TextMapPropagator<T>
opentelemetry::trace::TraceState::FromHeader(trace_state));
}

static SpanContext ExtractImpl(Getter getter, const T &carrier)
static SpanContext ExtractImpl(const TextMapCarrier &carrier)
{
nostd::string_view trace_parent = getter(carrier, kTraceParent);
nostd::string_view trace_state = getter(carrier, kTraceState);
nostd::string_view trace_parent = carrier.Get(kTraceParent);
nostd::string_view trace_state = carrier.Get(kTraceState);
if (trace_parent == "")
{
return SpanContext::GetInvalid();
Expand Down
22 changes: 7 additions & 15 deletions api/include/opentelemetry/trace/propagation/jaeger.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,10 @@ namespace propagation

static const nostd::string_view kTraceHeader = "uber-trace-id";

template <typename T>
class JaegerPropagator : public TextMapPropagator<T>
class JaegerPropagator : public TextMapPropagator
{
public:
using Getter = nostd::string_view (*)(const T &carrier, nostd::string_view trace_type);

using Setter = void (*)(T &carrier,
nostd::string_view trace_type,
nostd::string_view trace_description);

void Inject(Setter setter, T &carrier, const context::Context &context) noexcept override
void Inject(TextMapCarrier &carrier, const context::Context &context) noexcept override
{
SpanContext span_context = detail::GetCurrentSpan(context);
if (!span_context.IsValid())
Expand All @@ -60,14 +53,13 @@ class JaegerPropagator : public TextMapPropagator<T>
trace_identity[trace_id_length + span_id_length + 4] = '0';
trace_identity[trace_id_length + span_id_length + 5] = span_context.IsSampled() ? '1' : '0';

setter(carrier, kTraceHeader, nostd::string_view(trace_identity, sizeof(trace_identity)));
carrier.Set(kTraceHeader, nostd::string_view(trace_identity, sizeof(trace_identity)));
}

context::Context Extract(Getter getter,
const T &carrier,
context::Context Extract(const TextMapCarrier &carrier,
context::Context &context) noexcept override
{
SpanContext span_context = ExtractImpl(getter, carrier);
SpanContext span_context = ExtractImpl(carrier);
nostd::shared_ptr<Span> sp{new DefaultSpan(span_context)};
return context.SetValue(kSpanKey, sp);
}
Expand All @@ -81,9 +73,9 @@ class JaegerPropagator : public TextMapPropagator<T>
return TraceFlags(sampled);
}

static SpanContext ExtractImpl(Getter getter, const T &carrier)
static SpanContext ExtractImpl(const TextMapCarrier &carrier)
{
nostd::string_view trace_identity = getter(carrier, kTraceHeader);
nostd::string_view trace_identity = carrier.Get(kTraceHeader);

const size_t trace_field_count = 4;
nostd::string_view trace_fields[trace_field_count];
Expand Down
Loading