diff --git a/api/include/opentelemetry/trace/span_context.h b/api/include/opentelemetry/trace/span_context.h new file mode 100644 index 0000000000..fc04ce17e6 --- /dev/null +++ b/api/include/opentelemetry/trace/span_context.h @@ -0,0 +1,59 @@ +// Copyright 2020, 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 + +#include "opentelemetry/nostd/unique_ptr.h" +#include "opentelemetry/trace/span_id.h" +#include "opentelemetry/trace/trace_flags.h" +#include "opentelemetry/trace/trace_id.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace trace +{ +namespace trace_api = opentelemetry::trace; + +/* SpanContext contains the state that must propagate to child Spans and across + * process boundaries. It contains the identifiers TraceId and SpanId, + * TraceFlags, TraceState, and whether it has a remote parent. + * + * TODO: This is currently a placeholder class and requires revisiting + */ +class SpanContext final +{ +public: + /* A temporary constructor for an invalid SpanContext. + * @param sampled_flag a required parameter specifying if child spans should be + * sampled + * @param has_remote_parent a required parameter specifying if this context has + * a remote parent + */ + SpanContext(bool sampled_flag, bool has_remote_parent) : + trace_flags_(trace_api::TraceFlags((uint8_t) sampled_flag)), remote_parent_(has_remote_parent) {}; + + // @returns the trace_flags associated with this span_context + const trace_api::TraceFlags &trace_flags() const noexcept { return trace_flags_; } + + // @returns whether this context has the sampled flag set or not + bool IsSampled() const noexcept { return trace_flags_.IsSampled(); } + + // @returns whether this context has a remote parent or not + bool HasRemoteParent() const noexcept { return remote_parent_; } + +private: + const trace_api::TraceFlags trace_flags_; + const bool remote_parent_ = false; +}; +} // namespace trace +OPENTELEMETRY_END_NAMESPACE diff --git a/api/test/trace/BUILD b/api/test/trace/BUILD index ed3d584712..b3f194baa0 100644 --- a/api/test/trace/BUILD +++ b/api/test/trace/BUILD @@ -71,3 +71,14 @@ cc_test( "@com_google_googletest//:gtest_main", ], ) + +cc_test( + name = "span_context_test", + srcs = [ + "span_context_test.cc", + ], + deps = [ + "//api", + "@com_google_googletest//:gtest_main", + ], +) diff --git a/api/test/trace/CMakeLists.txt b/api/test/trace/CMakeLists.txt index f722ae4557..3439146f7a 100644 --- a/api/test/trace/CMakeLists.txt +++ b/api/test/trace/CMakeLists.txt @@ -1,5 +1,5 @@ foreach(testname key_value_iterable_view_test noop_test provider_test - span_id_test trace_id_test trace_flags_test) + span_id_test trace_id_test trace_flags_test span_context_test) add_executable(${testname} "${testname}.cc") target_link_libraries(${testname} ${GTEST_BOTH_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} opentelemetry_api) diff --git a/api/test/trace/span_context_test.cc b/api/test/trace/span_context_test.cc new file mode 100644 index 0000000000..661bba00bc --- /dev/null +++ b/api/test/trace/span_context_test.cc @@ -0,0 +1,38 @@ +#include "opentelemetry/trace/span_context.h" + +#include + +using opentelemetry::trace::SpanContext; + +TEST(SpanContextTest, IsSampled) +{ + SpanContext s1(true, true); + + ASSERT_EQ(s1.IsSampled(), true); + + SpanContext s2(false, true); + + ASSERT_EQ(s2.IsSampled(), false); +} + +TEST(SpanContextTest, HasRemoteParent) +{ + SpanContext s1(true, true); + + ASSERT_EQ(s1.HasRemoteParent(), true); + + SpanContext s2(true, false); + + ASSERT_EQ(s2.HasRemoteParent(), false); +} + +TEST(SpanContextTest, TraceFlags) +{ + SpanContext s1(true, true); + + ASSERT_EQ(s1.trace_flags().flags(), 1); + + SpanContext s2(false, true); + + ASSERT_EQ(s2.trace_flags().flags(), 0); +} diff --git a/sdk/include/opentelemetry/sdk/trace/sampler.h b/sdk/include/opentelemetry/sdk/trace/sampler.h index 27071b458c..35a0927404 100644 --- a/sdk/include/opentelemetry/sdk/trace/sampler.h +++ b/sdk/include/opentelemetry/sdk/trace/sampler.h @@ -4,6 +4,7 @@ #include "opentelemetry/trace/span.h" #include "opentelemetry/trace/trace_id.h" #include "opentelemetry/version.h" +#include "opentelemetry/trace/span_context.h" #include #include @@ -48,8 +49,6 @@ struct SamplingResult class Sampler { public: - // TODO: Remove this placeholder with real class - class SpanContext; virtual ~Sampler() = default; /** * Called during Span creation to make a sampling decision. @@ -66,7 +65,7 @@ class Sampler * @since 0.1.0 */ - virtual SamplingResult ShouldSample(const SpanContext *parent_context, + virtual SamplingResult ShouldSample(const trace_api::SpanContext *parent_context, trace_api::TraceId trace_id, nostd::string_view name, trace_api::SpanKind span_kind, diff --git a/sdk/include/opentelemetry/sdk/trace/samplers/always_off.h b/sdk/include/opentelemetry/sdk/trace/samplers/always_off.h index 0547068280..252cd9e4fd 100644 --- a/sdk/include/opentelemetry/sdk/trace/samplers/always_off.h +++ b/sdk/include/opentelemetry/sdk/trace/samplers/always_off.h @@ -8,6 +8,7 @@ namespace sdk namespace trace { namespace trace_api = opentelemetry::trace; + /** * The always off sampler always returns NOT_RECORD, effectively disabling * tracing functionality. @@ -19,7 +20,7 @@ class AlwaysOffSampler : public Sampler * @return Returns NOT_RECORD always */ SamplingResult ShouldSample( - const SpanContext * /*parent_context*/, + const trace_api::SpanContext * /*parent_context*/, trace_api::TraceId /*trace_id*/, nostd::string_view /*name*/, trace_api::SpanKind /*span_kind*/, diff --git a/sdk/include/opentelemetry/sdk/trace/samplers/always_on.h b/sdk/include/opentelemetry/sdk/trace/samplers/always_on.h index e50d15829f..5dd5f86457 100644 --- a/sdk/include/opentelemetry/sdk/trace/samplers/always_on.h +++ b/sdk/include/opentelemetry/sdk/trace/samplers/always_on.h @@ -8,6 +8,7 @@ namespace sdk namespace trace { namespace trace_api = opentelemetry::trace; + /** * The always on sampler is a default sampler which always return Decision::RECORD_AND_SAMPLE */ @@ -17,7 +18,7 @@ class AlwaysOnSampler : public Sampler /** * @return Always return Decision RECORD_AND_SAMPLE */ - inline SamplingResult ShouldSample(const SpanContext * /*parent_context*/, + inline SamplingResult ShouldSample(const trace_api::SpanContext * /*parent_context*/, trace_api::TraceId /*trace_id*/, nostd::string_view /*name*/, trace_api::SpanKind /*span_kind*/, diff --git a/sdk/include/opentelemetry/sdk/trace/samplers/parent_or_else.h b/sdk/include/opentelemetry/sdk/trace/samplers/parent_or_else.h index c562277957..aec9934604 100644 --- a/sdk/include/opentelemetry/sdk/trace/samplers/parent_or_else.h +++ b/sdk/include/opentelemetry/sdk/trace/samplers/parent_or_else.h @@ -10,21 +10,6 @@ namespace trace { namespace trace_api = opentelemetry::trace; -/** - * A placeholder class that stores the states of a span. - * Will be replaced by the real SpanContext class once it is implemented. - */ -class Sampler::SpanContext -{ -public: - inline explicit SpanContext(bool is_recording, bool sampled_flag) - : is_recording(is_recording), sampled_flag(sampled_flag) - {} - - bool is_recording; - bool sampled_flag; -}; - /** * The parent or else sampler is a composite sampler. ParentOrElse(delegateSampler) either respects * the parent span's sampling decision or delegates to delegateSampler for root spans. @@ -37,7 +22,7 @@ class ParentOrElseSampler : public Sampler * delegateSampler for root spans * @return Returns NOT_RECORD always */ - SamplingResult ShouldSample(const SpanContext * parent_context, + SamplingResult ShouldSample(const trace_api::SpanContext * parent_context, trace_api::TraceId trace_id, nostd::string_view name, trace_api::SpanKind span_kind, diff --git a/sdk/src/trace/samplers/parent_or_else.cc b/sdk/src/trace/samplers/parent_or_else.cc index fd0d909e84..2b56ab9d4b 100644 --- a/sdk/src/trace/samplers/parent_or_else.cc +++ b/sdk/src/trace/samplers/parent_or_else.cc @@ -11,7 +11,7 @@ ParentOrElseSampler::ParentOrElseSampler(std::shared_ptr delegate_sampl {} SamplingResult ParentOrElseSampler::ShouldSample( - const SpanContext *parent_context, + const trace_api::SpanContext *parent_context, trace_api::TraceId trace_id, nostd::string_view name, trace_api::SpanKind span_kind, @@ -24,7 +24,7 @@ SamplingResult ParentOrElseSampler::ShouldSample( } // If parent exists: - if (parent_context->sampled_flag) + if (parent_context->IsSampled()) { return {Decision::RECORD_AND_SAMPLE, nullptr}; } diff --git a/sdk/test/trace/parent_or_else_sampler_test.cc b/sdk/test/trace/parent_or_else_sampler_test.cc index 152121f4c3..93ce56dfb1 100644 --- a/sdk/test/trace/parent_or_else_sampler_test.cc +++ b/sdk/test/trace/parent_or_else_sampler_test.cc @@ -8,6 +8,7 @@ using opentelemetry::sdk::trace::AlwaysOffSampler; using opentelemetry::sdk::trace::AlwaysOnSampler; using opentelemetry::sdk::trace::Decision; using opentelemetry::sdk::trace::ParentOrElseSampler; +using opentelemetry::trace::SpanContext; TEST(ParentOrElseSampler, ShouldSample) { @@ -20,8 +21,8 @@ TEST(ParentOrElseSampler, ShouldSample) using M = std::map; M m1 = {{}}; opentelemetry::trace::KeyValueIterableView view{m1}; - opentelemetry::sdk::trace::Sampler::SpanContext parent_context_sampled(true, true); - opentelemetry::sdk::trace::Sampler::SpanContext parent_context_nonsampled(true, false); + SpanContext parent_context_sampled(true, false); + SpanContext parent_context_nonsampled(false, false); // Case 1: Parent doesn't exist. Return result of delegateSampler() auto sampling_result = sampler_off.ShouldSample(nullptr, trace_id, "", span_kind, view);