diff --git a/sdk/include/opentelemetry/sdk/trace/id_generator.h b/sdk/include/opentelemetry/sdk/trace/id_generator.h new file mode 100644 index 0000000000..ea2ec09725 --- /dev/null +++ b/sdk/include/opentelemetry/sdk/trace/id_generator.h @@ -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 \ No newline at end of file diff --git a/sdk/include/opentelemetry/sdk/trace/random_id_generator.h b/sdk/include/opentelemetry/sdk/trace/random_id_generator.h new file mode 100644 index 0000000000..70a8b68ed6 --- /dev/null +++ b/sdk/include/opentelemetry/sdk/trace/random_id_generator.h @@ -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 \ No newline at end of file diff --git a/sdk/include/opentelemetry/sdk/trace/tracer.h b/sdk/include/opentelemetry/sdk/trace/tracer.h index f764c48478..39af27ff7f 100644 --- a/sdk/include/opentelemetry/sdk/trace/tracer.h +++ b/sdk/include/opentelemetry/sdk/trace/tracer.h @@ -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(); } diff --git a/sdk/include/opentelemetry/sdk/trace/tracer_context.h b/sdk/include/opentelemetry/sdk/trace/tracer_context.h index e5af3a87ba..3d6c4faa44 100644 --- a/sdk/include/opentelemetry/sdk/trace/tracer_context.h +++ b/sdk/include/opentelemetry/sdk/trace/tracer_context.h @@ -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" @@ -28,11 +29,13 @@ namespace trace class TracerContext { public: - explicit TracerContext(std::unique_ptr processor, - opentelemetry::sdk::resource::Resource resource = - opentelemetry::sdk::resource::Resource::Create({}), - std::unique_ptr sampler = - std::unique_ptr(new AlwaysOnSampler)) noexcept; + explicit TracerContext( + std::unique_ptr processor, + opentelemetry::sdk::resource::Resource resource = + opentelemetry::sdk::resource::Resource::Create({}), + std::unique_ptr sampler = std::unique_ptr(new AlwaysOnSampler), + std::unique_ptr id_generator = + std::unique_ptr(new RandomIdGenerator())) noexcept; /** * Attaches a span processor to this tracer context. * @@ -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. @@ -77,6 +86,7 @@ class TracerContext opentelemetry::sdk::common::AtomicUniquePtr processor_; opentelemetry::sdk::resource::Resource resource_; std::unique_ptr sampler_; + std::unique_ptr id_generator_; }; } // namespace trace diff --git a/sdk/include/opentelemetry/sdk/trace/tracer_provider.h b/sdk/include/opentelemetry/sdk/trace/tracer_provider.h index 0301aa7e44..a82e29ccef 100644 --- a/sdk/include/opentelemetry/sdk/trace/tracer_provider.h +++ b/sdk/include/opentelemetry/sdk/trace/tracer_provider.h @@ -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 processor, - opentelemetry::sdk::resource::Resource resource = - opentelemetry::sdk::resource::Resource::Create({}), - std::unique_ptr sampler = - std::unique_ptr(new AlwaysOnSampler)) noexcept; + explicit TracerProvider( + std::unique_ptr processor, + opentelemetry::sdk::resource::Resource resource = + opentelemetry::sdk::resource::Resource::Create({}), + std::unique_ptr sampler = std::unique_ptr(new AlwaysOnSampler), + std::unique_ptr id_generator = + std::unique_ptr( + new RandomIdGenerator())) noexcept; /** * Initialize a new tracer provider with a specified context diff --git a/sdk/src/trace/CMakeLists.txt b/sdk/src/trace/CMakeLists.txt index e3d3e0afec..ddef00fb42 100644 --- a/sdk/src/trace/CMakeLists.txt +++ b/sdk/src/trace/CMakeLists.txt @@ -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) diff --git a/sdk/src/trace/random_id_generator.cc b/sdk/src/trace/random_id_generator.cc new file mode 100644 index 0000000000..431f183ef6 --- /dev/null +++ b/sdk/src/trace/random_id_generator.cc @@ -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 diff --git a/sdk/src/trace/span.cc b/sdk/src/trace/span.cc index 388d0ab923..caffc733bd 100644 --- a/sdk/src/trace/span.cc +++ b/sdk/src/trace/span.cc @@ -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, nostd::string_view name, const opentelemetry::common::KeyValueIterable &attributes, @@ -77,7 +61,7 @@ Span::Span(std::shared_ptr &&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; @@ -89,7 +73,7 @@ Span::Span(std::shared_ptr &&tracer, } else { - trace_id = GenerateRandomTraceId(); + trace_id = tracer_->GetIdGenerator().GenerateTraceId(); } span_context_ = std::unique_ptr(new trace_api::SpanContext( diff --git a/sdk/src/trace/tracer_context.cc b/sdk/src/trace/tracer_context.cc index a463ec81d4..8dc5397dc9 100644 --- a/sdk/src/trace/tracer_context.cc +++ b/sdk/src/trace/tracer_context.cc @@ -9,8 +9,12 @@ namespace trace TracerContext::TracerContext(std::unique_ptr processor, opentelemetry::sdk::resource::Resource resource, - std::unique_ptr sampler) noexcept - : processor_(std::move(processor)), resource_(resource), sampler_(std::move(sampler)) + std::unique_ptr sampler, + std::unique_ptr id_generator) noexcept + : processor_(std::move(processor)), + resource_(resource), + sampler_(std::move(sampler)), + id_generator_(std::move(id_generator)) {} Sampler &TracerContext::GetSampler() const noexcept @@ -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 processor) noexcept { // TODO(jsuereth): Implement diff --git a/sdk/src/trace/tracer_provider.cc b/sdk/src/trace/tracer_provider.cc index 0eaf6782f2..479ba8a462 100644 --- a/sdk/src/trace/tracer_provider.cc +++ b/sdk/src/trace/tracer_provider.cc @@ -11,9 +11,12 @@ TracerProvider::TracerProvider(std::shared_ptr contex TracerProvider::TracerProvider(std::unique_ptr processor, opentelemetry::sdk::resource::Resource resource, - std::unique_ptr sampler) noexcept - : TracerProvider( - std::make_shared(std::move(processor), resource, std::move(sampler))) + std::unique_ptr sampler, + std::unique_ptr id_generator) noexcept + : TracerProvider(std::make_shared(std::move(processor), + resource, + std::move(sampler), + std::move(id_generator))) {} opentelemetry::nostd::shared_ptr TracerProvider::GetTracer( diff --git a/sdk/test/trace/tracer_provider_test.cc b/sdk/test/trace/tracer_provider_test.cc index 55a5a9be44..a1308827d5 100644 --- a/sdk/test/trace/tracer_provider_test.cc +++ b/sdk/test/trace/tracer_provider_test.cc @@ -33,7 +33,8 @@ TEST(TracerProvider, GetTracer) ASSERT_EQ("AlwaysOnSampler", sdkTracer1->GetSampler().GetDescription()); TracerProvider tp2(std::make_shared( std::unique_ptr(new SimpleSpanProcessor(nullptr)), Resource::Create({}), - std::unique_ptr(new AlwaysOffSampler()))); + std::unique_ptr(new AlwaysOffSampler()), + std::unique_ptr(new RandomIdGenerator))); auto sdkTracer2 = dynamic_cast(tp2.GetTracer("test").get()); ASSERT_EQ("AlwaysOffSampler", sdkTracer2->GetSampler().GetDescription()); } diff --git a/sdk/test/trace/tracer_test.cc b/sdk/test/trace/tracer_test.cc index 176a949670..dbfa3146f3 100644 --- a/sdk/test/trace/tracer_test.cc +++ b/sdk/test/trace/tracer_test.cc @@ -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 initTracer(std::unique_ptr &&exporter) @@ -57,12 +75,14 @@ std::shared_ptr initTracer(std::unique_ptr initTracer( std::unique_ptr &&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(new SimpleSpanProcessor(std::move(exporter))); auto resource = Resource::Create({}); auto context = std::make_shared(std::move(processor), resource, - std::unique_ptr(sampler)); + std::unique_ptr(sampler), + std::unique_ptr(id_generator)); return std::shared_ptr(new Tracer(context)); } } // namespace @@ -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 exporter(new InMemorySpanExporter()); + std::shared_ptr 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 exporter(new InMemorySpanExporter());