Skip to content

Commit

Permalink
Support Custom span-id and trace-id generator (#681)
Browse files Browse the repository at this point in the history
  • Loading branch information
lalitb authored Apr 21, 2021
1 parent ae060d1 commit 2e7594e
Show file tree
Hide file tree
Showing 12 changed files with 203 additions and 37 deletions.
42 changes: 42 additions & 0 deletions sdk/include/opentelemetry/sdk/trace/id_generator.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// Copyright 2021, 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/trace/span_id.h"
#include "opentelemetry/trace/trace_id.h"
#include "opentelemetry/version.h"

OPENTELEMETRY_BEGIN_NAMESPACE
namespace sdk
{
namespace trace
{

/** IdGenerator provides an interface for generating Trace Id and Span Id */
class IdGenerator
{

public:
virtual ~IdGenerator() = default;

/** Returns a SpanId represented by opaque 128-bit trace identifier */
virtual opentelemetry::trace::SpanId GenerateSpanId() noexcept = 0;

/** Returns a TraceId represented by opaque 64-bit trace identifier */
virtual opentelemetry::trace::TraceId GenerateTraceId() noexcept = 0;
};
} // namespace trace

} // namespace sdk
OPENTELEMETRY_END_NAMESPACE
35 changes: 35 additions & 0 deletions sdk/include/opentelemetry/sdk/trace/random_id_generator.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Copyright 2021, 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/sdk/trace/id_generator.h"

OPENTELEMETRY_BEGIN_NAMESPACE
namespace sdk
{
namespace trace
{

class RandomIdGenerator : public IdGenerator
{
public:
opentelemetry::trace::SpanId GenerateSpanId() noexcept override;

opentelemetry::trace::TraceId GenerateTraceId() noexcept override;
};

} // namespace trace

} // namespace sdk
OPENTELEMETRY_END_NAMESPACE
3 changes: 3 additions & 0 deletions sdk/include/opentelemetry/sdk/trace/tracer.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ class Tracer final : public trace_api::Tracer, public std::enable_shared_from_th
/** Returns the currently active span processor. */
SpanProcessor &GetActiveProcessor() noexcept { return context_->GetActiveProcessor(); }

/** Returns the configured Id generator */
IdGenerator &GetIdGenerator() noexcept { return context_->GetIdGenerator(); }

// Note: Test only
Sampler &GetSampler() { return context_->GetSampler(); }

Expand Down
20 changes: 15 additions & 5 deletions sdk/include/opentelemetry/sdk/trace/tracer_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "opentelemetry/sdk/common/atomic_unique_ptr.h"
#include "opentelemetry/sdk/resource/resource.h"
#include "opentelemetry/sdk/trace/processor.h"
#include "opentelemetry/sdk/trace/random_id_generator.h"
#include "opentelemetry/sdk/trace/samplers/always_on.h"
#include "opentelemetry/version.h"

Expand All @@ -28,11 +29,13 @@ namespace trace
class TracerContext
{
public:
explicit TracerContext(std::unique_ptr<SpanProcessor> processor,
opentelemetry::sdk::resource::Resource resource =
opentelemetry::sdk::resource::Resource::Create({}),
std::unique_ptr<Sampler> sampler =
std::unique_ptr<AlwaysOnSampler>(new AlwaysOnSampler)) noexcept;
explicit TracerContext(
std::unique_ptr<SpanProcessor> processor,
opentelemetry::sdk::resource::Resource resource =
opentelemetry::sdk::resource::Resource::Create({}),
std::unique_ptr<Sampler> sampler = std::unique_ptr<AlwaysOnSampler>(new AlwaysOnSampler),
std::unique_ptr<IdGenerator> id_generator =
std::unique_ptr<IdGenerator>(new RandomIdGenerator())) noexcept;
/**
* Attaches a span processor to this tracer context.
*
Expand Down Expand Up @@ -61,6 +64,12 @@ class TracerContext
*/
const opentelemetry::sdk::resource::Resource &GetResource() const noexcept;

/**
* Obtain the Id Generator associated with this tracer context.
* @return The ID Generator for this tracer context.
*/
opentelemetry::sdk::trace::IdGenerator &GetIdGenerator() const noexcept;

/**
* Force all active SpanProcessors to flush any buffered spans
* within the given timeout.
Expand All @@ -77,6 +86,7 @@ class TracerContext
opentelemetry::sdk::common::AtomicUniquePtr<SpanProcessor> processor_;
opentelemetry::sdk::resource::Resource resource_;
std::unique_ptr<Sampler> sampler_;
std::unique_ptr<IdGenerator> id_generator_;
};

} // namespace trace
Expand Down
13 changes: 8 additions & 5 deletions sdk/include/opentelemetry/sdk/trace/tracer_provider.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,14 @@ class TracerProvider final : public opentelemetry::trace::TracerProvider
* @param sampler The sampler for this tracer provider. This must
* not be a nullptr.
*/
explicit TracerProvider(std::unique_ptr<SpanProcessor> processor,
opentelemetry::sdk::resource::Resource resource =
opentelemetry::sdk::resource::Resource::Create({}),
std::unique_ptr<Sampler> sampler =
std::unique_ptr<AlwaysOnSampler>(new AlwaysOnSampler)) noexcept;
explicit TracerProvider(
std::unique_ptr<SpanProcessor> processor,
opentelemetry::sdk::resource::Resource resource =
opentelemetry::sdk::resource::Resource::Create({}),
std::unique_ptr<Sampler> sampler = std::unique_ptr<AlwaysOnSampler>(new AlwaysOnSampler),
std::unique_ptr<opentelemetry::sdk::trace::IdGenerator> id_generator =
std::unique_ptr<opentelemetry::sdk::trace::IdGenerator>(
new RandomIdGenerator())) noexcept;

/**
* Initialize a new tracer provider with a specified context
Expand Down
3 changes: 2 additions & 1 deletion sdk/src/trace/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ add_library(
span.cc
batch_span_processor.cc
samplers/parent.cc
samplers/trace_id_ratio.cc)
samplers/trace_id_ratio.cc
random_id_generator.cc)

set_target_properties(opentelemetry_trace PROPERTIES EXPORT_NAME trace)

Expand Down
40 changes: 40 additions & 0 deletions sdk/src/trace/random_id_generator.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Copyright 2021, 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.

#include "opentelemetry/sdk/trace/random_id_generator.h"
#include "opentelemetry/version.h"
#include "src/common/random.h"

OPENTELEMETRY_BEGIN_NAMESPACE
namespace sdk
{
namespace trace
{

opentelemetry::trace::SpanId RandomIdGenerator::GenerateSpanId() noexcept
{
uint8_t span_id_buf[opentelemetry::trace::SpanId::kSize];
sdk::common::Random::GenerateRandomBuffer(span_id_buf);
return opentelemetry::trace::SpanId(span_id_buf);
}

opentelemetry::trace::TraceId RandomIdGenerator::GenerateTraceId() noexcept
{
uint8_t trace_id_buf[opentelemetry::trace::TraceId::kSize];
sdk::common::Random::GenerateRandomBuffer(trace_id_buf);
return opentelemetry::trace::TraceId(trace_id_buf);
}
} // namespace trace
} // namespace sdk
OPENTELEMETRY_END_NAMESPACE
20 changes: 2 additions & 18 deletions sdk/src/trace/span.cc
Original file line number Diff line number Diff line change
Expand Up @@ -41,22 +41,6 @@ SteadyTimestamp NowOr(const SteadyTimestamp &steady)
}
} // namespace

// Helper function to generate random trace id.
trace_api::TraceId GenerateRandomTraceId()
{
uint8_t trace_id_buf[trace_api::TraceId::kSize];
sdk::common::Random::GenerateRandomBuffer(trace_id_buf);
return trace_api::TraceId(trace_id_buf);
}

// Helper function to generate random span id.
trace_api::SpanId GenerateRandomSpanId()
{
uint8_t span_id_buf[trace_api::SpanId::kSize];
sdk::common::Random::GenerateRandomBuffer(span_id_buf);
return trace_api::SpanId(span_id_buf);
}

Span::Span(std::shared_ptr<Tracer> &&tracer,
nostd::string_view name,
const opentelemetry::common::KeyValueIterable &attributes,
Expand All @@ -77,7 +61,7 @@ Span::Span(std::shared_ptr<Tracer> &&tracer,
recordable_->SetName(name);

trace_api::TraceId trace_id;
trace_api::SpanId span_id = GenerateRandomSpanId();
trace_api::SpanId span_id = tracer_->GetIdGenerator().GenerateSpanId();
trace_api::SpanId parent_span_id;
bool is_parent_span_valid = false;

Expand All @@ -89,7 +73,7 @@ Span::Span(std::shared_ptr<Tracer> &&tracer,
}
else
{
trace_id = GenerateRandomTraceId();
trace_id = tracer_->GetIdGenerator().GenerateTraceId();
}

span_context_ = std::unique_ptr<trace_api::SpanContext>(new trace_api::SpanContext(
Expand Down
13 changes: 11 additions & 2 deletions sdk/src/trace/tracer_context.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,12 @@ namespace trace

TracerContext::TracerContext(std::unique_ptr<SpanProcessor> processor,
opentelemetry::sdk::resource::Resource resource,
std::unique_ptr<Sampler> sampler) noexcept
: processor_(std::move(processor)), resource_(resource), sampler_(std::move(sampler))
std::unique_ptr<Sampler> sampler,
std::unique_ptr<IdGenerator> id_generator) noexcept
: processor_(std::move(processor)),
resource_(resource),
sampler_(std::move(sampler)),
id_generator_(std::move(id_generator))
{}

Sampler &TracerContext::GetSampler() const noexcept
Expand All @@ -23,6 +27,11 @@ const opentelemetry::sdk::resource::Resource &TracerContext::GetResource() const
return resource_;
}

opentelemetry::sdk::trace::IdGenerator &TracerContext::GetIdGenerator() const noexcept
{
return *id_generator_;
}

void TracerContext::RegisterPipeline(std::unique_ptr<SpanProcessor> processor) noexcept
{
// TODO(jsuereth): Implement
Expand Down
9 changes: 6 additions & 3 deletions sdk/src/trace/tracer_provider.cc
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,12 @@ TracerProvider::TracerProvider(std::shared_ptr<sdk::trace::TracerContext> contex

TracerProvider::TracerProvider(std::unique_ptr<SpanProcessor> processor,
opentelemetry::sdk::resource::Resource resource,
std::unique_ptr<Sampler> sampler) noexcept
: TracerProvider(
std::make_shared<TracerContext>(std::move(processor), resource, std::move(sampler)))
std::unique_ptr<Sampler> sampler,
std::unique_ptr<IdGenerator> id_generator) noexcept
: TracerProvider(std::make_shared<TracerContext>(std::move(processor),
resource,
std::move(sampler),
std::move(id_generator)))
{}

opentelemetry::nostd::shared_ptr<opentelemetry::trace::Tracer> TracerProvider::GetTracer(
Expand Down
3 changes: 2 additions & 1 deletion sdk/test/trace/tracer_provider_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ TEST(TracerProvider, GetTracer)
ASSERT_EQ("AlwaysOnSampler", sdkTracer1->GetSampler().GetDescription());
TracerProvider tp2(std::make_shared<TracerContext>(
std::unique_ptr<SpanProcessor>(new SimpleSpanProcessor(nullptr)), Resource::Create({}),
std::unique_ptr<Sampler>(new AlwaysOffSampler())));
std::unique_ptr<Sampler>(new AlwaysOffSampler()),
std::unique_ptr<IdGenerator>(new RandomIdGenerator)));
auto sdkTracer2 = dynamic_cast<Tracer *>(tp2.GetTracer("test").get());
ASSERT_EQ("AlwaysOffSampler", sdkTracer2->GetSampler().GetDescription());
}
Expand Down
39 changes: 37 additions & 2 deletions sdk/test/trace/tracer_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,24 @@ class MockSampler final : public Sampler
nostd::string_view GetDescription() const noexcept override { return "MockSampler"; }
};

/**
* A Mock Custom Id Generator
*/
class MockIdGenerator : public IdGenerator
{
opentelemetry::trace::SpanId GenerateSpanId() noexcept override
{
return opentelemetry::trace::SpanId(buf_span);
}

opentelemetry::trace::TraceId GenerateTraceId() noexcept override
{
return opentelemetry::trace::TraceId(buf_trace);
}
uint8_t buf_span[8] = {1, 2, 3, 4, 5, 6, 7, 8};
uint8_t buf_trace[16] = {1, 2, 3, 4, 5, 6, 7, 8, 8, 7, 6, 5, 4, 3, 2, 1};
};

namespace
{
std::shared_ptr<opentelemetry::trace::Tracer> initTracer(std::unique_ptr<SpanExporter> &&exporter)
Expand All @@ -57,12 +75,14 @@ std::shared_ptr<opentelemetry::trace::Tracer> initTracer(std::unique_ptr<SpanExp
std::shared_ptr<opentelemetry::trace::Tracer> initTracer(
std::unique_ptr<SpanExporter> &&exporter,
// For testing, just shove a pointer over, we'll take it over.
Sampler *sampler)
Sampler *sampler,
IdGenerator *id_generator = new RandomIdGenerator)
{
auto processor = std::unique_ptr<SpanProcessor>(new SimpleSpanProcessor(std::move(exporter)));
auto resource = Resource::Create({});
auto context = std::make_shared<TracerContext>(std::move(processor), resource,
std::unique_ptr<Sampler>(sampler));
std::unique_ptr<Sampler>(sampler),
std::unique_ptr<IdGenerator>(id_generator));
return std::shared_ptr<opentelemetry::trace::Tracer>(new Tracer(context));
}
} // namespace
Expand Down Expand Up @@ -132,6 +152,21 @@ TEST(Tracer, StartSpanSampleOff)
ASSERT_EQ(0, span_data->GetSpans().size());
}

TEST(Tracer, StartSpanCustomIdGenerator)
{
IdGenerator *id_generator = new MockIdGenerator();
std::unique_ptr<InMemorySpanExporter> exporter(new InMemorySpanExporter());
std::shared_ptr<InMemorySpanData> span_data = exporter->GetData();
auto tracer = initTracer(std::move(exporter), new AlwaysOnSampler(), id_generator);

tracer->StartSpan("span 1")->End();
auto spans = span_data->GetSpans();
auto &cur_span_data = spans.at(0);

EXPECT_EQ(cur_span_data->GetTraceId(), id_generator->GenerateTraceId());
EXPECT_EQ(cur_span_data->GetSpanId(), id_generator->GenerateSpanId());
}

TEST(Tracer, StartSpanWithOptionsTime)
{
std::unique_ptr<InMemorySpanExporter> exporter(new InMemorySpanExporter());
Expand Down

0 comments on commit 2e7594e

Please sign in to comment.