diff --git a/sdk/src/trace/span.cc b/sdk/src/trace/span.cc index c6c3151a7f..c27c071b62 100644 --- a/sdk/src/trace/span.cc +++ b/sdk/src/trace/span.cc @@ -2,6 +2,7 @@ #include "src/common/random.h" #include "opentelemetry/context/runtime_context.h" +#include "opentelemetry/trace/trace_flags.h" #include "opentelemetry/version.h" OPENTELEMETRY_BEGIN_NAMESPACE @@ -77,16 +78,22 @@ Span::Span(std::shared_ptr &&tracer, } recordable_->SetName(name); + trace_api::TraceId trace_id; + trace_api::SpanId span_id = GenerateRandomSpanId(); + if (parent_span_context.IsValid()) { - recordable_->SetIds(parent_span_context.trace_id(), GenerateRandomSpanId(), - parent_span_context.span_id()); + trace_id = parent_span_context.trace_id(); + recordable_->SetIds(trace_id, span_id, parent_span_context.span_id()); } else { - recordable_->SetIds(GenerateRandomTraceId(), GenerateRandomSpanId(), trace_api::SpanId()); + trace_id = GenerateRandomTraceId(); + recordable_->SetIds(trace_id, span_id, trace_api::SpanId()); } - // TODO: Create and populate SpanContext for this span when SpanContext is fully implemented + + span_context_ = std::unique_ptr( + new trace_api::SpanContext(trace_id, span_id, trace_api::TraceFlags(), false)); attributes.ForEachKeyValue([&](nostd::string_view key, opentelemetry::common::AttributeValue value) noexcept { diff --git a/sdk/src/trace/tracer.cc b/sdk/src/trace/tracer.cc index 3923a47161..f7b2d38033 100644 --- a/sdk/src/trace/tracer.cc +++ b/sdk/src/trace/tracer.cc @@ -30,6 +30,20 @@ std::shared_ptr Tracer::GetSampler() const noexcept return sampler_; } +// Helper function to extract the current span context from the runtime context. +// Returns an invalid span context if the runtime context doesn't contain a span. +trace_api::SpanContext GetCurrentSpanContext() +{ + context::ContextValue curr_span_context = context::RuntimeContext::GetValue(SpanKey); + + if (nostd::holds_alternative>(curr_span_context)) + { + auto curr_span = nostd::get>(curr_span_context); + return curr_span->GetContext(); + } + return trace_api::SpanContext(); +} + nostd::shared_ptr Tracer::StartSpan( nostd::string_view name, const trace_api::KeyValueIterable &attributes, @@ -47,13 +61,9 @@ nostd::shared_ptr Tracer::StartSpan( } else { - // TODO: Get parent span context from current context. For now we assume all spans - // have no parent, and pass an invalid parent span context to the Span constructor. - const trace_api::SpanContext kInvalidParentSpanContext(false, false); - auto span = nostd::shared_ptr{ new (std::nothrow) Span{this->shared_from_this(), processor_.load(), name, attributes, - options, kInvalidParentSpanContext}}; + options, GetCurrentSpanContext()}}; span->SetToken( nostd::unique_ptr(new context::Token(context::RuntimeContext::Attach( diff --git a/sdk/test/trace/tracer_test.cc b/sdk/test/trace/tracer_test.cc index efdc6b6f8b..891cce22d4 100644 --- a/sdk/test/trace/tracer_test.cc +++ b/sdk/test/trace/tracer_test.cc @@ -113,11 +113,16 @@ TEST(Tracer, ToMockSpanExporter) ASSERT_EQ("span 2", spans_received->at(0)->GetName()); EXPECT_TRUE(spans_received->at(0)->GetTraceId().IsValid()); EXPECT_TRUE(spans_received->at(0)->GetSpanId().IsValid()); - EXPECT_FALSE(spans_received->at(0)->GetParentSpanId().IsValid()); + EXPECT_TRUE(spans_received->at(0)->GetParentSpanId().IsValid()); span_first->End(); ASSERT_EQ(2, spans_received->size()); + // Verify trace and parent span id propagation + EXPECT_EQ(span_second->GetContext().trace_id(), span_first->GetContext().trace_id()); + EXPECT_EQ(spans_received->at(0)->GetTraceId(), spans_received->at(1)->GetTraceId()); + EXPECT_EQ(spans_received->at(0)->GetParentSpanId(), spans_received->at(1)->GetSpanId()); + ASSERT_EQ("span 1", spans_received->at(1)->GetName()); EXPECT_TRUE(spans_received->at(1)->GetTraceId().IsValid()); EXPECT_TRUE(spans_received->at(1)->GetSpanId().IsValid());