diff --git a/api/include/opentelemetry/trace/span.h b/api/include/opentelemetry/trace/span.h index 87b64747cf..77de4050d4 100644 --- a/api/include/opentelemetry/trace/span.h +++ b/api/include/opentelemetry/trace/span.h @@ -7,7 +7,6 @@ #include "opentelemetry/common/attribute_value.h" #include "opentelemetry/common/key_value_iterable_view.h" -#include "opentelemetry/common/timestamp.h" #include "opentelemetry/nostd/shared_ptr.h" #include "opentelemetry/nostd/span.h" #include "opentelemetry/nostd/string_view.h" @@ -15,72 +14,14 @@ #include "opentelemetry/nostd/unique_ptr.h" #include "opentelemetry/trace/canonical_code.h" #include "opentelemetry/trace/span_context.h" +#include "opentelemetry/trace/span_metadata.h" + #include "opentelemetry/version.h" OPENTELEMETRY_BEGIN_NAMESPACE namespace trace { -// The key identifies the active span in the current context. -constexpr char kSpanKey[] = "active_span"; - -enum class SpanKind -{ - kInternal, - kServer, - kClient, - kProducer, - kConsumer, -}; - -// StatusCode - Represents the canonical set of status codes of a finished Span. - -enum class StatusCode -{ - kUnset, // default status - kOk, // Operation has completed successfully. - kError // The operation contains an error -}; - -/** - * StartSpanOptions provides options to set properties of a Span at the time of - * its creation - */ -struct StartSpanOptions -{ - // Optionally sets the start time of a Span. - // - // If the start time of a Span is set, timestamps from both the system clock - // and steady clock must be provided. - // - // Timestamps from the steady clock can be used to most accurately measure a - // Span's duration, while timestamps from the system clock can be used to most - // accurately place a Span's - // time point relative to other Spans collected across a distributed system. - common::SystemTimestamp start_system_time; - common::SteadyTimestamp start_steady_time; - - // Explicitly set the parent of a Span. - // - // This defaults to an invalid span context. In this case, the Span is - // automatically parented to the currently active span. - SpanContext parent = SpanContext::GetInvalid(); - - // TODO: - // SpanContext remote_parent; - // Links - SpanKind kind = SpanKind::kInternal; -}; -/** - * StartEndOptions provides options to set properties of a Span when it is - * ended. - */ -struct EndSpanOptions -{ - // Optionally sets the end time of a Span. - common::SteadyTimestamp end_steady_time; -}; - class Tracer; /** @@ -176,7 +117,7 @@ class Span * @param options can be used to manually define span properties like the end * timestamp */ - virtual void End(const EndSpanOptions &options = {}) noexcept = 0; + virtual void End(const trace::EndSpanOptions &options = {}) noexcept = 0; virtual trace::SpanContext GetContext() const noexcept = 0; diff --git a/api/include/opentelemetry/trace/span_metadata.h b/api/include/opentelemetry/trace/span_metadata.h new file mode 100644 index 0000000000..977329a151 --- /dev/null +++ b/api/include/opentelemetry/trace/span_metadata.h @@ -0,0 +1,43 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "opentelemetry/common/timestamp.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace trace +{ + +enum class SpanKind +{ + kInternal, + kServer, + kClient, + kProducer, + kConsumer, +}; + +// The key identifies the active span in the current context. +constexpr char kSpanKey[] = "active_span"; + +// StatusCode - Represents the canonical set of status codes of a finished Span. +enum class StatusCode +{ + kUnset, // default status + kOk, // Operation has completed successfully. + kError // The operation contains an error +}; + +/** + * EndSpanOptions provides options to set properties of a Span when it is + * ended. + */ +struct EndSpanOptions +{ + // Optionally sets the end time of a Span. + common::SteadyTimestamp end_steady_time; +}; + +} // namespace trace +OPENTELEMETRY_END_NAMESPACE \ No newline at end of file diff --git a/api/include/opentelemetry/trace/span_startoptions.h b/api/include/opentelemetry/trace/span_startoptions.h new file mode 100644 index 0000000000..688b768bd0 --- /dev/null +++ b/api/include/opentelemetry/trace/span_startoptions.h @@ -0,0 +1,45 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "opentelemetry/context/context.h" +#include "opentelemetry/trace/span_context.h" +#include "opentelemetry/trace/span_metadata.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace trace +{ + +/** + * StartSpanOptions provides options to set properties of a Span at the time of + * its creation + */ +struct StartSpanOptions +{ + // Optionally sets the start time of a Span. + // + // If the start time of a Span is set, timestamps from both the system clock + // and steady clock must be provided. + // + // Timestamps from the steady clock can be used to most accurately measure a + // Span's duration, while timestamps from the system clock can be used to most + // accurately place a Span's + // time point relative to other Spans collected across a distributed system. + common::SystemTimestamp start_system_time; + common::SteadyTimestamp start_steady_time; + + // Explicitly set the parent of a Span. + // + // This defaults to an invalid span context. In this case, the Span is + // automatically parented to the currently active span. + nostd::variant parent = SpanContext::GetInvalid(); + + // TODO: + // SpanContext remote_parent; + // Links + SpanKind kind = SpanKind::kInternal; +}; + +} // namespace trace +OPENTELEMETRY_END_NAMESPACE \ No newline at end of file diff --git a/api/include/opentelemetry/trace/tracer.h b/api/include/opentelemetry/trace/tracer.h index 425e085116..b60336a48d 100644 --- a/api/include/opentelemetry/trace/tracer.h +++ b/api/include/opentelemetry/trace/tracer.h @@ -3,6 +3,7 @@ #pragma once +#include "opentelemetry/context/context.h" #include "opentelemetry/nostd/shared_ptr.h" #include "opentelemetry/nostd/string_view.h" #include "opentelemetry/nostd/unique_ptr.h" @@ -10,6 +11,7 @@ #include "opentelemetry/trace/scope.h" #include "opentelemetry/trace/span.h" #include "opentelemetry/trace/span_context_kv_iterable_view.h" +#include "opentelemetry/trace/span_startoptions.h" #include "opentelemetry/version.h" #include @@ -17,7 +19,6 @@ OPENTELEMETRY_BEGIN_NAMESPACE namespace trace { - /** * Handles span creation and in-process context propagation. * diff --git a/exporters/etw/include/opentelemetry/exporters/etw/etw_tracer.h b/exporters/etw/include/opentelemetry/exporters/etw/etw_tracer.h index 2806bfa593..47e6fa79c4 100644 --- a/exporters/etw/include/opentelemetry/exporters/etw/etw_tracer.h +++ b/exporters/etw/include/opentelemetry/exporters/etw/etw_tracer.h @@ -569,8 +569,15 @@ class Tracer : public trace::Tracer // Parent Context: // - either use current span // - or attach to parent SpanContext specified in options - const auto parentContext = - (options.parent.IsValid()) ? options.parent : GetCurrentSpan()->GetContext(); + trace::SpanContext parentContext = GetCurrentSpan()->GetContext(); + if (nostd::holds_alternative(options.parent)) + { + auto span_context = nostd::get(options.parent); + if (span_context.IsValid()) + { + parentContext = span_context; + } + } // Populate Etw.RelatedActivityId at envelope level if enabled GUID RelatedActivityId; @@ -1089,8 +1096,9 @@ class TracerProvider : public trace::TracerProvider // identifier, see EventActivityIdControl. GetOption(options, "enableActivityId", config_.enableActivityId, false); - // Map parent `SpanId` to RelatedActivityId - Activity identifier from the previous component. - // Use this parameter to link your component's events to the previous component's events. + // Map parent `SpanId` to RelatedActivityId - Activity identifier from the previous + // component. Use this parameter to link your component's events to the previous component's + // events. GetOption(options, "enableRelatedActivityId", config_.enableRelatedActivityId, false); // When a new Span is started, the current span automatically becomes its parent. diff --git a/exporters/otlp/test/otlp_http_exporter_test.cc b/exporters/otlp/test/otlp_http_exporter_test.cc index 2dfd32ce05..daab046439 100644 --- a/exporters/otlp/test/otlp_http_exporter_test.cc +++ b/exporters/otlp/test/otlp_http_exporter_test.cc @@ -222,7 +222,9 @@ TEST_F(OtlpHttpExporterTestPeer, ExportJsonIntegrationTest) child_span->End(); parent_span->End(); - child_span_opts.parent.trace_id().ToLowerBase16(MakeSpan(trace_id_hex)); + nostd::get(child_span_opts.parent) + .trace_id() + .ToLowerBase16(MakeSpan(trace_id_hex)); report_trace_id.assign(trace_id_hex, sizeof(trace_id_hex)); } @@ -282,7 +284,9 @@ TEST_F(OtlpHttpExporterTestPeer, ExportBinaryIntegrationTest) child_span->End(); parent_span->End(); - child_span_opts.parent.trace_id().CopyBytesTo(MakeSpan(trace_id_binary)); + nostd::get(child_span_opts.parent) + .trace_id() + .CopyBytesTo(MakeSpan(trace_id_binary)); report_trace_id.assign(reinterpret_cast(trace_id_binary), sizeof(trace_id_binary)); } diff --git a/sdk/src/trace/tracer.cc b/sdk/src/trace/tracer.cc index 977722d0ca..be5e5f7d96 100644 --- a/sdk/src/trace/tracer.cc +++ b/sdk/src/trace/tracer.cc @@ -5,6 +5,7 @@ #include "opentelemetry/context/runtime_context.h" #include "opentelemetry/nostd/shared_ptr.h" #include "opentelemetry/sdk/common/atomic_shared_ptr.h" +#include "opentelemetry/trace/context.h" #include "opentelemetry/version.h" #include "src/trace/span.h" @@ -27,8 +28,25 @@ nostd::shared_ptr Tracer::StartSpan( const trace_api::SpanContextKeyValueIterable &links, const trace_api::StartSpanOptions &options) noexcept { - trace_api::SpanContext parent_context = - options.parent.IsValid() ? options.parent : GetCurrentSpan()->GetContext(); + trace_api::SpanContext parent_context = GetCurrentSpan()->GetContext(); + if (nostd::holds_alternative(options.parent)) + { + auto span_context = nostd::get(options.parent); + if (span_context.IsValid()) + { + parent_context = span_context; + } + } + else if (nostd::holds_alternative(options.parent)) + { + auto context = nostd::get(options.parent); + // fetch span context from parent span stored in the context + auto span_context = opentelemetry::trace::GetSpan(context)->GetContext(); + if (span_context.IsValid()) + { + parent_context = span_context; + } + } trace_api::TraceId trace_id; trace_api::SpanId span_id = GetIdGenerator().GenerateSpanId(); diff --git a/sdk/test/trace/tracer_test.cc b/sdk/test/trace/tracer_test.cc index 92659a8a5a..94e57a4cd7 100644 --- a/sdk/test/trace/tracer_test.cc +++ b/sdk/test/trace/tracer_test.cc @@ -9,6 +9,7 @@ #include "opentelemetry/sdk/trace/samplers/parent.h" #include "opentelemetry/sdk/trace/simple_processor.h" #include "opentelemetry/sdk/trace/span_data.h" +#include "opentelemetry/trace/context.h" #include @@ -621,6 +622,44 @@ TEST(Tracer, ExpectParent) EXPECT_EQ(spandata_second->GetSpanId(), spandata_third->GetParentSpanId()); } +TEST(Tracer, ExpectParentAsContext) +{ + std::unique_ptr exporter(new InMemorySpanExporter()); + std::shared_ptr span_data = exporter->GetData(); + auto tracer = initTracer(std::move(exporter)); + auto spans = span_data.get()->GetSpans(); + + ASSERT_EQ(0, spans.size()); + + auto span_first = tracer->StartSpan("span 1"); + + opentelemetry::context::Context c1; + auto c2 = trace_api::SetSpan(c1, span_first); + trace_api::StartSpanOptions options; + options.parent = c2; + auto span_second = tracer->StartSpan("span 2", options); + + auto c3 = trace_api::SetSpan(c2, span_second); + options.parent = c3; + auto span_third = tracer->StartSpan("span 3", options); + + span_third->End(); + span_second->End(); + span_first->End(); + + spans = span_data->GetSpans(); + ASSERT_EQ(3, spans.size()); + auto spandata_first = std::move(spans.at(2)); + auto spandata_second = std::move(spans.at(1)); + auto spandata_third = std::move(spans.at(0)); + EXPECT_EQ("span 1", spandata_first->GetName()); + EXPECT_EQ("span 2", spandata_second->GetName()); + EXPECT_EQ("span 3", spandata_third->GetName()); + + EXPECT_EQ(spandata_first->GetSpanId(), spandata_second->GetParentSpanId()); + EXPECT_EQ(spandata_second->GetSpanId(), spandata_third->GetParentSpanId()); +} + TEST(Tracer, ValidTraceIdToSampler) { std::unique_ptr exporter(new InMemorySpanExporter());