Skip to content

Commit

Permalink
Provide span for opentracing shim inject
Browse files Browse the repository at this point in the history
The various propagation injectors will attempt to retrieve the
Span from the context that is provided in the api call:

  void Inject(context::propagation::TextMapCarrier &carrier,
              const context::Context &context) noexcept override

The shim will provide the RuntimeContext augmented with the baggage
to the Inject method. Unfortunately, the shim does not add the span
to the RuntimeContext. It does not instantiate a Scope.

This commit adds a Span to the context passed into Inject by
modifying the shim.
  • Loading branch information
karusher authored and Mark Klein committed Feb 15, 2024
1 parent c7a88c4 commit e5bece9
Show file tree
Hide file tree
Showing 3 changed files with 137 additions and 4 deletions.
17 changes: 13 additions & 4 deletions opentracing-shim/src/tracer_shim.cc
Original file line number Diff line number Diff line change
Expand Up @@ -124,12 +124,21 @@ opentracing::expected<void> TracerShim::injectImpl(const opentracing::SpanContex
if (auto context_shim = SpanContextShim::extractFrom(&sc))
{
auto current_context = opentelemetry::context::RuntimeContext::GetCurrent();
// It MUST inject any non-empty Baggage even amidst no valid SpanContext.
const auto &context =
opentelemetry::baggage::SetBaggage(current_context, context_shim->baggage());

// Inject dummy span to provide SpanContext information
auto span_context = opentelemetry::trace::SpanContext(
context_shim->context().trace_id(), context_shim->context().span_id(),
context_shim->context().trace_flags(), false);
opentelemetry::nostd::shared_ptr<opentelemetry::trace::Span> sp{
new opentelemetry::trace::DefaultSpan(span_context)};
auto context_with_span = opentelemetry::trace::SetSpan(current_context, sp);

// Inject any non-empty Baggage
const auto &context_with_span_baggage =
opentelemetry::baggage::SetBaggage(context_with_span, context_shim->baggage());

CarrierWriterShim carrier{writer};
propagator->Inject(carrier, context);
propagator->Inject(carrier, context_with_span_baggage);
return opentracing::make_expected();
}

Expand Down
30 changes: 30 additions & 0 deletions opentracing-shim/test/shim_mocks.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,18 @@ struct MockTracerProvider final : public trace_api::TracerProvider

struct MockPropagator : public context::propagation::TextMapPropagator
{
static constexpr const char *kTraceIdKey = "trace_id";
static constexpr const char *kSpanIdKey = "span_id";
static constexpr const char *kTraceFlagsKey = "trace_flags_id";

template <class T, int N>
static inline std::string ToLowerBase16(const T &id)
{
char buf[N] = {0};
id.ToLowerBase16(buf);
return std::string(buf, sizeof(buf));
}

// Returns the context that is stored in the carrier with the TextMapCarrier as extractor.
context::Context Extract(const context::propagation::TextMapCarrier &carrier,
context::Context &context) noexcept override
Expand All @@ -140,6 +152,24 @@ struct MockPropagator : public context::propagation::TextMapPropagator
carrier.Set(k, v);
return true;
});

auto span_key_value = context.GetValue(trace_api::kSpanKey);
if (nostd::holds_alternative<nostd::shared_ptr<trace_api::Span>>(span_key_value))
{
auto span = nostd::get<nostd::shared_ptr<trace_api::Span>>(span_key_value);
if (span)
{
// Store span context information in TextMapCarrier to allow verifying propagation
auto span_context = span->GetContext();
carrier.Set(kTraceIdKey, ToLowerBase16<trace_api::TraceId, 2 * trace_api::TraceId::kSize>(
span_context.trace_id()));
carrier.Set(kSpanIdKey, ToLowerBase16<trace_api::SpanId, 2 * trace_api::SpanId::kSize>(
span_context.span_id()));
carrier.Set(kTraceFlagsKey,
ToLowerBase16<trace_api::TraceFlags, 2>(span_context.trace_flags()));
}
}

is_injected = true;
}

Expand Down
94 changes: 94 additions & 0 deletions opentracing-shim/test/tracer_shim_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -218,3 +218,97 @@ TEST_F(TracerShimTest, ExtractOnlyBaggage)
ASSERT_TRUE(span_context_shim->BaggageItem("foo", value));
ASSERT_EQ(value, "bar");
}

class TracerWithSpanContext : public trace_api::Tracer
{
public:
nostd::shared_ptr<trace_api::Span> StartSpan(
nostd::string_view name,
const common::KeyValueIterable & /* attributes */,
const trace_api::SpanContextKeyValueIterable & /* links */,
const trace_api::StartSpanOptions & /* options */) noexcept override
{
constexpr uint8_t trace_id_buf[] = {1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8};
trace_api::TraceId trace_id(trace_id_buf);

constexpr uint8_t span_id_buf[] = {1, 2, 3, 4, 5, 6, 7, 8};
trace_api::SpanId span_id(span_id_buf);

auto span_context = trace_api::SpanContext(trace_id, span_id, GetTraceFlags(), false);
nostd::shared_ptr<trace_api::Span> result(new trace_api::DefaultSpan(span_context));

return result;
}

void ForceFlushWithMicroseconds(uint64_t /* timeout */) noexcept override {}

void CloseWithMicroseconds(uint64_t /* timeout */) noexcept override {}

static trace_api::TraceFlags GetTraceFlags()
{
return trace_api::TraceFlags(trace_api::TraceFlags::kIsSampled);
}
};

class TracerWithSpanContextProvider : public trace_api::TracerProvider
{
public:
static nostd::shared_ptr<trace_api::TracerProvider> Create()
{
nostd::shared_ptr<trace_api::TracerProvider> result(new TracerWithSpanContextProvider());
return result;
}

#if OPENTELEMETRY_ABI_VERSION_NO >= 2
nostd::shared_ptr<trace_api::Tracer> GetTracer(
nostd::string_view /* name */,
nostd::string_view /* version */,
nostd::string_view /* schema_url */,
const common::KeyValueIterable * /* attributes */) noexcept override
{
nostd::shared_ptr<trace_api::Tracer> result(new TracerWithSpanContext());
return result;
}
#else
nostd::shared_ptr<trace_api::Tracer> GetTracer(
nostd::string_view /* name */,
nostd::string_view /* version */,
nostd::string_view /* schema_url */) noexcept override
{
nostd::shared_ptr<trace_api::Tracer> result(new TracerWithSpanContext());
return result;
}
#endif
};

TEST_F(TracerShimTest, InjectSpanKey)
{
using context::propagation::TextMapPropagator;

auto local_text_map_format = new MockPropagator();
auto local_http_headers_format = new MockPropagator();

ASSERT_FALSE(local_text_map_format->is_injected);
ASSERT_FALSE(local_http_headers_format->is_injected);

nostd::shared_ptr<trace_api::TracerProvider> tracer_provider =
TracerWithSpanContextProvider::Create();
auto local_tracer_shim = shim::TracerShim::createTracerShim(
tracer_provider,
{.text_map = nostd::shared_ptr<TextMapPropagator>(local_text_map_format),
.http_headers = nostd::shared_ptr<TextMapPropagator>(local_http_headers_format)});

std::unordered_map<std::string, std::string> text_map;
auto span_shim = local_tracer_shim->StartSpan("a");
local_tracer_shim->Inject(span_shim->context(), TextMapCarrier{text_map});

ASSERT_TRUE(local_text_map_format->is_injected);
ASSERT_FALSE(local_http_headers_format->is_injected);

ASSERT_EQ(span_shim->context().ToTraceID(), text_map[MockPropagator::kTraceIdKey]);
ASSERT_EQ(span_shim->context().ToSpanID(), text_map[MockPropagator::kSpanIdKey]);

char flag_buffer[2];
TracerWithSpanContext::GetTraceFlags().ToLowerBase16(flag_buffer);
ASSERT_EQ(std::string(flag_buffer), text_map[MockPropagator::kTraceFlagsKey]);
}

0 comments on commit e5bece9

Please sign in to comment.