Skip to content
59 changes: 59 additions & 0 deletions api/include/opentelemetry/trace/span_context.h
Original file line number Diff line number Diff line change
@@ -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_; }
Comment thread
nholbrook marked this conversation as resolved.

private:
const trace_api::TraceFlags trace_flags_;
const bool remote_parent_ = false;
};
} // namespace trace
OPENTELEMETRY_END_NAMESPACE
11 changes: 11 additions & 0 deletions api/test/trace/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -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",
],
)
2 changes: 1 addition & 1 deletion api/test/trace/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -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)
Expand Down
38 changes: 38 additions & 0 deletions api/test/trace/span_context_test.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#include "opentelemetry/trace/span_context.h"

#include <gtest/gtest.h>

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);
}
5 changes: 2 additions & 3 deletions sdk/include/opentelemetry/sdk/trace/sampler.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 <map>
#include <memory>
Expand Down Expand Up @@ -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.
Expand All @@ -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,
Expand Down
3 changes: 2 additions & 1 deletion sdk/include/opentelemetry/sdk/trace/samplers/always_off.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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*/,
Expand Down
3 changes: 2 additions & 1 deletion sdk/include/opentelemetry/sdk/trace/samplers/always_on.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
*/
Expand All @@ -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*/,
Expand Down
17 changes: 1 addition & 16 deletions sdk/include/opentelemetry/sdk/trace/samplers/parent_or_else.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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,
Expand Down
4 changes: 2 additions & 2 deletions sdk/src/trace/samplers/parent_or_else.cc
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ ParentOrElseSampler::ParentOrElseSampler(std::shared_ptr<Sampler> 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,
Expand All @@ -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};
}
Expand Down
5 changes: 3 additions & 2 deletions sdk/test/trace/parent_or_else_sampler_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand All @@ -20,8 +21,8 @@ TEST(ParentOrElseSampler, ShouldSample)
using M = std::map<std::string, int>;
M m1 = {{}};
opentelemetry::trace::KeyValueIterableView<M> 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);
Expand Down