Skip to content

Commit

Permalink
Provide span for opentracing shim inject (#2535)
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 Feb 26, 2024
1 parent 563094b commit 84e38b2
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, 2), text_map[MockPropagator::kTraceFlagsKey]);
}

1 comment on commit 84e38b2

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Performance Alert ⚠️

Possible performance regression was detected for benchmark 'OpenTelemetry-cpp api Benchmark'.
Benchmark result of this commit is worse than the previous benchmark result exceeding threshold 2.

Benchmark suite Current: 84e38b2 Previous: 563094b Ratio
BM_SpinLockThrashing/1/process_time/real_time 0.15675020217895508 ms/iter 0.07686364023309004 ms/iter 2.04
BM_NaiveSpinLockThrashing/2/process_time/real_time 0.660055691433936 ms/iter 0.17726421356201172 ms/iter 3.72

This comment was automatically generated by workflow using github-action-benchmark.

Please sign in to comment.