From 7cf05ff98724291e5e2d125f34f4571eb0689e09 Mon Sep 17 00:00:00 2001 From: Jakob Lovhall Date: Sat, 2 May 2026 22:52:30 +0200 Subject: [PATCH 01/15] do not use MultiSpanProcessor for single processors --- .../opentelemetry/sdk/trace/tracer_context.h | 1 + sdk/src/trace/tracer_context.cc | 46 +++++++++++++++++-- 2 files changed, 42 insertions(+), 5 deletions(-) diff --git a/sdk/include/opentelemetry/sdk/trace/tracer_context.h b/sdk/include/opentelemetry/sdk/trace/tracer_context.h index 518c1cbdf6..1f27701fed 100644 --- a/sdk/include/opentelemetry/sdk/trace/tracer_context.h +++ b/sdk/include/opentelemetry/sdk/trace/tracer_context.h @@ -129,6 +129,7 @@ class TracerContext std::unique_ptr id_generator_; std::unique_ptr processor_; std::unique_ptr> tracer_configurator_; + uint16_t num_processors_; }; } // namespace trace diff --git a/sdk/src/trace/tracer_context.cc b/sdk/src/trace/tracer_context.cc index adb3cfe538..67c5cbd770 100644 --- a/sdk/src/trace/tracer_context.cc +++ b/sdk/src/trace/tracer_context.cc @@ -33,9 +33,22 @@ TracerContext::TracerContext(std::vector> &&proce : resource_(resource), sampler_(std::move(sampler)), id_generator_(std::move(id_generator)), - processor_(std::unique_ptr(new MultiSpanProcessor(std::move(processors)))), - tracer_configurator_(std::move(tracer_configurator)) -{} + tracer_configurator_(std::move(tracer_configurator)), + num_processors_(0) +{ + if (processors.empty()) + { + processor_ = std::unique_ptr(new MultiSpanProcessor(std::move(processors))); + } + else + { + // at least one processor is available here + for (auto &&processor : processors) + { + AddProcessor(std::move(processor)); + } + } +} Sampler &TracerContext::GetSampler() const noexcept { @@ -60,9 +73,32 @@ opentelemetry::sdk::trace::IdGenerator &TracerContext::GetIdGenerator() const no void TracerContext::AddProcessor(std::unique_ptr processor) noexcept { + if (!processor) + { + return; + } + + if (num_processors_ == 0) + { + // this is the first processor to be added, maybe the MultiSpanProcessor is not needed + processor_ = std::move(processor); + } + else if (num_processors_ == 1) + { + // if there already is a processor, then make a new MultiSpanProcessor to handle both + std::unique_ptr multi_processor(new MultiSpanProcessor({})); + multi_processor->AddProcessor(std::move(processor_)); + multi_processor->AddProcessor(std::move(processor)); + processor_ = std::move(multi_processor); + } + else /*if (num_processors_ > 1)*/ + { + // already have a MultiSpanProcessor, add the processor to it + auto multi_processor = static_cast(processor_.get()); + multi_processor->AddProcessor(std::move(processor)); + } - auto multi_processor = static_cast(processor_.get()); - multi_processor->AddProcessor(std::move(processor)); + ++num_processors_; } void TracerContext::SetTracerConfigurator( From 04a566f69c1ca014f627e352e6366e65f90f452a Mon Sep 17 00:00:00 2001 From: Jakob Lovhall Date: Tue, 12 May 2026 21:22:51 +0200 Subject: [PATCH 02/15] add some tests --- sdk/test/trace/tracer_provider_test.cc | 67 ++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/sdk/test/trace/tracer_provider_test.cc b/sdk/test/trace/tracer_provider_test.cc index 687f63d07f..cf839d508c 100644 --- a/sdk/test/trace/tracer_provider_test.cc +++ b/sdk/test/trace/tracer_provider_test.cc @@ -25,6 +25,7 @@ #include "opentelemetry/sdk/trace/samplers/always_off.h" #include "opentelemetry/sdk/trace/samplers/always_on.h" #include "opentelemetry/sdk/trace/simple_processor.h" +#include "opentelemetry/sdk/trace/multi_span_processor.h" #include "opentelemetry/sdk/trace/simple_processor_factory.h" #include "opentelemetry/sdk/trace/tracer.h" #include "opentelemetry/sdk/trace/tracer_config.h" @@ -329,6 +330,72 @@ TEST(TracerProvider, GetTracerAbiv2) } #endif /* OPENTELEMETRY_ABI_VERSION_NO >= 2 */ +// get the same processor back, not wrapped in a MultiSpanProcessor +TEST(TracerProvider, GetProcessor) +{ + std::unique_ptr processor(new SimpleSpanProcessor(nullptr)); + std::vector> processors; + processors.push_back(std::move(processor)); + + std::unique_ptr context1(new TracerContext(std::move(processors))); + + auto & span_processor = context1->GetProcessor(); + + // Should be the SimpleSpanProcessor processor that was created above. +#ifdef OPENTELEMETRY_RTTI_ENABLED + auto processor_typeed = dynamic_cast(&span_processor); +#else + auto processor_typeed = static_cast(&span_processor); +#endif + ASSERT_NE(nullptr, processor_typeed); +} + +// get a MultiSpanProcessor back that wraps both processors +TEST(TracerProvider, GetProcessorsTwo) +{ + std::unique_ptr processor1(new SimpleSpanProcessor(nullptr)); + std::unique_ptr processor2(new SimpleSpanProcessor(nullptr)); + std::vector> processors; + processors.push_back(std::move(processor1)); + processors.push_back(std::move(processor2)); + + std::unique_ptr context1(new TracerContext(std::move(processors))); + + auto & span_processor = context1->GetProcessor(); + + // Should be the SimpleSpanProcessor processor that was created above. +#ifdef OPENTELEMETRY_RTTI_ENABLED + auto processor_typeed = dynamic_cast(&span_processor); +#else + auto processor_typeed = static_cast(&span_processor); +#endif + ASSERT_NE(nullptr, processor_typeed); +} + +// get a MultiSpanProcessor back that wraps all three processors +TEST(TracerProvider, GetProcessorsThree) +{ + std::unique_ptr processor1(new SimpleSpanProcessor(nullptr)); + std::unique_ptr processor2(new SimpleSpanProcessor(nullptr)); + std::unique_ptr processor3(new SimpleSpanProcessor(nullptr)); + std::vector> processors; + processors.push_back(std::move(processor1)); + processors.push_back(std::move(processor2)); + processors.push_back(std::move(processor3)); + + std::unique_ptr context1(new TracerContext(std::move(processors))); + + auto & span_processor = context1->GetProcessor(); + + // Should be the SimpleSpanProcessor processor that was created above. +#ifdef OPENTELEMETRY_RTTI_ENABLED + auto processor_typeed = dynamic_cast(&span_processor); +#else + auto processor_typeed = static_cast(&span_processor); +#endif + ASSERT_NE(nullptr, processor_typeed); +} + TEST(TracerProvider, Shutdown) { std::unique_ptr processor(new SimpleSpanProcessor(nullptr)); From fc3af4400c80303aa84167264ca815a746d63ba1 Mon Sep 17 00:00:00 2001 From: Jakob Lovhall Date: Tue, 12 May 2026 21:25:45 +0200 Subject: [PATCH 03/15] format --- sdk/test/trace/tracer_provider_test.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sdk/test/trace/tracer_provider_test.cc b/sdk/test/trace/tracer_provider_test.cc index cf839d508c..26b47dcc55 100644 --- a/sdk/test/trace/tracer_provider_test.cc +++ b/sdk/test/trace/tracer_provider_test.cc @@ -339,7 +339,7 @@ TEST(TracerProvider, GetProcessor) std::unique_ptr context1(new TracerContext(std::move(processors))); - auto & span_processor = context1->GetProcessor(); + auto &span_processor = context1->GetProcessor(); // Should be the SimpleSpanProcessor processor that was created above. #ifdef OPENTELEMETRY_RTTI_ENABLED @@ -361,7 +361,7 @@ TEST(TracerProvider, GetProcessorsTwo) std::unique_ptr context1(new TracerContext(std::move(processors))); - auto & span_processor = context1->GetProcessor(); + auto &span_processor = context1->GetProcessor(); // Should be the SimpleSpanProcessor processor that was created above. #ifdef OPENTELEMETRY_RTTI_ENABLED @@ -385,7 +385,7 @@ TEST(TracerProvider, GetProcessorsThree) std::unique_ptr context1(new TracerContext(std::move(processors))); - auto & span_processor = context1->GetProcessor(); + auto &span_processor = context1->GetProcessor(); // Should be the SimpleSpanProcessor processor that was created above. #ifdef OPENTELEMETRY_RTTI_ENABLED From 4bcf2513408bf1d439ec0b17baf185314d811a7b Mon Sep 17 00:00:00 2001 From: Jakob Lovhall Date: Wed, 13 May 2026 00:04:58 +0200 Subject: [PATCH 04/15] format again --- sdk/test/trace/tracer_provider_test.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/test/trace/tracer_provider_test.cc b/sdk/test/trace/tracer_provider_test.cc index 26b47dcc55..336728e720 100644 --- a/sdk/test/trace/tracer_provider_test.cc +++ b/sdk/test/trace/tracer_provider_test.cc @@ -19,13 +19,13 @@ #include "opentelemetry/sdk/resource/resource.h" #include "opentelemetry/sdk/trace/exporter.h" #include "opentelemetry/sdk/trace/id_generator.h" +#include "opentelemetry/sdk/trace/multi_span_processor.h" #include "opentelemetry/sdk/trace/processor.h" #include "opentelemetry/sdk/trace/random_id_generator.h" #include "opentelemetry/sdk/trace/sampler.h" #include "opentelemetry/sdk/trace/samplers/always_off.h" #include "opentelemetry/sdk/trace/samplers/always_on.h" #include "opentelemetry/sdk/trace/simple_processor.h" -#include "opentelemetry/sdk/trace/multi_span_processor.h" #include "opentelemetry/sdk/trace/simple_processor_factory.h" #include "opentelemetry/sdk/trace/tracer.h" #include "opentelemetry/sdk/trace/tracer_config.h" From 6d78235e81b5e543b2247742921e8560702971bc Mon Sep 17 00:00:00 2001 From: Jakob Lovhall Date: Wed, 13 May 2026 21:10:37 +0200 Subject: [PATCH 05/15] pointer implementation instead of counter --- .../opentelemetry/sdk/trace/tracer_context.h | 6 +++++- sdk/src/trace/tracer_context.cc | 21 ++++++++++--------- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/sdk/include/opentelemetry/sdk/trace/tracer_context.h b/sdk/include/opentelemetry/sdk/trace/tracer_context.h index 1f27701fed..8d3d226790 100644 --- a/sdk/include/opentelemetry/sdk/trace/tracer_context.h +++ b/sdk/include/opentelemetry/sdk/trace/tracer_context.h @@ -23,6 +23,9 @@ namespace sdk namespace trace { +// forward declare to be able to have a raw pointer to it +class MultiSpanProcessor; + /** * A class which stores the TracerProvider context. * @@ -129,7 +132,8 @@ class TracerContext std::unique_ptr id_generator_; std::unique_ptr processor_; std::unique_ptr> tracer_configurator_; - uint16_t num_processors_; + // shares the pointer with processor_ if it is a MultiSpanProcessor, null otherwise + MultiSpanProcessor *multi_processor_; }; } // namespace trace diff --git a/sdk/src/trace/tracer_context.cc b/sdk/src/trace/tracer_context.cc index 67c5cbd770..9ecd2406bd 100644 --- a/sdk/src/trace/tracer_context.cc +++ b/sdk/src/trace/tracer_context.cc @@ -34,7 +34,7 @@ TracerContext::TracerContext(std::vector> &&proce sampler_(std::move(sampler)), id_generator_(std::move(id_generator)), tracer_configurator_(std::move(tracer_configurator)), - num_processors_(0) + multi_processor_(nullptr) { if (processors.empty()) { @@ -78,27 +78,28 @@ void TracerContext::AddProcessor(std::unique_ptr processor) noexc return; } - if (num_processors_ == 0) + if (!processor_) { - // this is the first processor to be added, maybe the MultiSpanProcessor is not needed + // this is the first processor to be added processor_ = std::move(processor); } - else if (num_processors_ == 1) + else if (multi_processor_ == nullptr) { - // if there already is a processor, then make a new MultiSpanProcessor to handle both + // if there already is a processor, but its not a MultiSpanProcessor. make a new MultiSpanProcessor std::unique_ptr multi_processor(new MultiSpanProcessor({})); multi_processor->AddProcessor(std::move(processor_)); multi_processor->AddProcessor(std::move(processor)); + + // duplicate the pointer before it gets type erased + multi_processor_ = multi_processor.get(); + processor_ = std::move(multi_processor); } - else /*if (num_processors_ > 1)*/ + else /*if (multi_processor_ != nullptr)*/ { // already have a MultiSpanProcessor, add the processor to it - auto multi_processor = static_cast(processor_.get()); - multi_processor->AddProcessor(std::move(processor)); + multi_processor_->AddProcessor(std::move(processor)); } - - ++num_processors_; } void TracerContext::SetTracerConfigurator( From c62b8bbf85ccca091cb30e8c79b9a7602faa92b9 Mon Sep 17 00:00:00 2001 From: Jakob Lovhall Date: Wed, 13 May 2026 21:14:32 +0200 Subject: [PATCH 06/15] format --- sdk/src/trace/tracer_context.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/src/trace/tracer_context.cc b/sdk/src/trace/tracer_context.cc index 9ecd2406bd..b7a8ca03e9 100644 --- a/sdk/src/trace/tracer_context.cc +++ b/sdk/src/trace/tracer_context.cc @@ -85,7 +85,7 @@ void TracerContext::AddProcessor(std::unique_ptr processor) noexc } else if (multi_processor_ == nullptr) { - // if there already is a processor, but its not a MultiSpanProcessor. make a new MultiSpanProcessor + // a processor exists, but it's not a MultiSpanProcessor. make a new MultiSpanProcessor std::unique_ptr multi_processor(new MultiSpanProcessor({})); multi_processor->AddProcessor(std::move(processor_)); multi_processor->AddProcessor(std::move(processor)); From 57975a24e107f54bb32bd0f152746cb2506630cf Mon Sep 17 00:00:00 2001 From: Jakob Lovhall Date: Wed, 13 May 2026 21:25:45 +0200 Subject: [PATCH 07/15] try to get past cppcheck --- sdk/src/trace/tracer_context.cc | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sdk/src/trace/tracer_context.cc b/sdk/src/trace/tracer_context.cc index b7a8ca03e9..dd1eb5eaf7 100644 --- a/sdk/src/trace/tracer_context.cc +++ b/sdk/src/trace/tracer_context.cc @@ -86,13 +86,11 @@ void TracerContext::AddProcessor(std::unique_ptr processor) noexc else if (multi_processor_ == nullptr) { // a processor exists, but it's not a MultiSpanProcessor. make a new MultiSpanProcessor - std::unique_ptr multi_processor(new MultiSpanProcessor({})); + multi_processor_ = new MultiSpanProcessor({}); + std::unique_ptr multi_processor(multi_processor_); multi_processor->AddProcessor(std::move(processor_)); multi_processor->AddProcessor(std::move(processor)); - // duplicate the pointer before it gets type erased - multi_processor_ = multi_processor.get(); - processor_ = std::move(multi_processor); } else /*if (multi_processor_ != nullptr)*/ From 9ea0b083ef8c21208811b09ac55d815ef17297c1 Mon Sep 17 00:00:00 2001 From: Jakob Lovhall Date: Thu, 14 May 2026 17:08:44 +0200 Subject: [PATCH 08/15] verify more in tests --- .../sdk/trace/multi_span_processor.h | 3 ++ sdk/test/trace/tracer_provider_test.cc | 54 +++++++++++++++++-- 2 files changed, 52 insertions(+), 5 deletions(-) diff --git a/sdk/include/opentelemetry/sdk/trace/multi_span_processor.h b/sdk/include/opentelemetry/sdk/trace/multi_span_processor.h index 7b0172dc8e..85caf5f1a1 100644 --- a/sdk/include/opentelemetry/sdk/trace/multi_span_processor.h +++ b/sdk/include/opentelemetry/sdk/trace/multi_span_processor.h @@ -194,6 +194,9 @@ class MultiSpanProcessor : public SpanProcessor ProcessorNode *head_{nullptr}; ProcessorNode *tail_{nullptr}; size_t count_{0}; + + // For testing + friend class MultiSpanProcessorTestPeer; }; } // namespace trace } // namespace sdk diff --git a/sdk/test/trace/tracer_provider_test.cc b/sdk/test/trace/tracer_provider_test.cc index 336728e720..62f1557e4e 100644 --- a/sdk/test/trace/tracer_provider_test.cc +++ b/sdk/test/trace/tracer_provider_test.cc @@ -50,6 +50,34 @@ using namespace opentelemetry::sdk::trace; using namespace opentelemetry::sdk::resource; using opentelemetry::sdk::instrumentationscope::ScopeConfigurator; +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace trace +{ +class MultiSpanProcessorTestPeer +{ +public: + static + std::vector GetProcessors(MultiSpanProcessor * multi_span_processor) + { + std::vector res; + + MultiSpanProcessor::ProcessorNode *node = multi_span_processor->head_; + while (node != nullptr) + { + auto processor = node->value_.get(); + res.emplace_back(processor); + node = node->next_; + } + + return res; + } +}; +} +} +OPENTELEMETRY_END_NAMESPACE + TEST(TracerProvider, GetTracer) { std::unique_ptr processor(new SimpleSpanProcessor(nullptr)); @@ -353,8 +381,13 @@ TEST(TracerProvider, GetProcessor) // get a MultiSpanProcessor back that wraps both processors TEST(TracerProvider, GetProcessorsTwo) { - std::unique_ptr processor1(new SimpleSpanProcessor(nullptr)); - std::unique_ptr processor2(new SimpleSpanProcessor(nullptr)); + std::vector processors_raw(2); + processors_raw[0] = new SimpleSpanProcessor(nullptr); // deleted via unique_ptr + processors_raw[1] = new SimpleSpanProcessor(nullptr); // deleted via unique_ptr + + std::unique_ptr processor1(processors_raw[0]); + std::unique_ptr processor2(processors_raw[1]); + std::vector> processors; processors.push_back(std::move(processor1)); processors.push_back(std::move(processor2)); @@ -370,14 +403,22 @@ TEST(TracerProvider, GetProcessorsTwo) auto processor_typeed = static_cast(&span_processor); #endif ASSERT_NE(nullptr, processor_typeed); + + std::vector contained_processors = MultiSpanProcessorTestPeer::GetProcessors(processor_typeed); + EXPECT_EQ(processors_raw, contained_processors); } // get a MultiSpanProcessor back that wraps all three processors TEST(TracerProvider, GetProcessorsThree) { - std::unique_ptr processor1(new SimpleSpanProcessor(nullptr)); - std::unique_ptr processor2(new SimpleSpanProcessor(nullptr)); - std::unique_ptr processor3(new SimpleSpanProcessor(nullptr)); + std::vector processors_raw(3); + processors_raw[0] = new SimpleSpanProcessor(nullptr); // deleted via unique_ptr + processors_raw[1] = new SimpleSpanProcessor(nullptr); // deleted via unique_ptr + processors_raw[2] = new SimpleSpanProcessor(nullptr); // deleted via unique_ptr + + std::unique_ptr processor1(processors_raw[0]); + std::unique_ptr processor2(processors_raw[1]); + std::unique_ptr processor3(processors_raw[2]); std::vector> processors; processors.push_back(std::move(processor1)); processors.push_back(std::move(processor2)); @@ -394,6 +435,9 @@ TEST(TracerProvider, GetProcessorsThree) auto processor_typeed = static_cast(&span_processor); #endif ASSERT_NE(nullptr, processor_typeed); + + std::vector contained_processors = MultiSpanProcessorTestPeer::GetProcessors(processor_typeed); + EXPECT_EQ(processors_raw, contained_processors); } TEST(TracerProvider, Shutdown) From d64ed3599861a81dd492a301d92492597a7eb062 Mon Sep 17 00:00:00 2001 From: Jakob Lovhall Date: Thu, 14 May 2026 21:34:03 +0200 Subject: [PATCH 09/15] format --- sdk/test/trace/tracer_provider_test.cc | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/sdk/test/trace/tracer_provider_test.cc b/sdk/test/trace/tracer_provider_test.cc index 62f1557e4e..4663c633d2 100644 --- a/sdk/test/trace/tracer_provider_test.cc +++ b/sdk/test/trace/tracer_provider_test.cc @@ -381,9 +381,9 @@ TEST(TracerProvider, GetProcessor) // get a MultiSpanProcessor back that wraps both processors TEST(TracerProvider, GetProcessorsTwo) { - std::vector processors_raw(2); - processors_raw[0] = new SimpleSpanProcessor(nullptr); // deleted via unique_ptr - processors_raw[1] = new SimpleSpanProcessor(nullptr); // deleted via unique_ptr + std::vector processors_raw(2); + processors_raw[0] = new SimpleSpanProcessor(nullptr); // deleted via unique_ptr + processors_raw[1] = new SimpleSpanProcessor(nullptr); // deleted via unique_ptr std::unique_ptr processor1(processors_raw[0]); std::unique_ptr processor2(processors_raw[1]); @@ -404,17 +404,18 @@ TEST(TracerProvider, GetProcessorsTwo) #endif ASSERT_NE(nullptr, processor_typeed); - std::vector contained_processors = MultiSpanProcessorTestPeer::GetProcessors(processor_typeed); + std::vector contained_processors = + MultiSpanProcessorTestPeer::GetProcessors(processor_typeed); EXPECT_EQ(processors_raw, contained_processors); } // get a MultiSpanProcessor back that wraps all three processors TEST(TracerProvider, GetProcessorsThree) { - std::vector processors_raw(3); - processors_raw[0] = new SimpleSpanProcessor(nullptr); // deleted via unique_ptr - processors_raw[1] = new SimpleSpanProcessor(nullptr); // deleted via unique_ptr - processors_raw[2] = new SimpleSpanProcessor(nullptr); // deleted via unique_ptr + std::vector processors_raw(3); + processors_raw[0] = new SimpleSpanProcessor(nullptr); // deleted via unique_ptr + processors_raw[1] = new SimpleSpanProcessor(nullptr); // deleted via unique_ptr + processors_raw[2] = new SimpleSpanProcessor(nullptr); // deleted via unique_ptr std::unique_ptr processor1(processors_raw[0]); std::unique_ptr processor2(processors_raw[1]); @@ -436,7 +437,8 @@ TEST(TracerProvider, GetProcessorsThree) #endif ASSERT_NE(nullptr, processor_typeed); - std::vector contained_processors = MultiSpanProcessorTestPeer::GetProcessors(processor_typeed); + std::vector contained_processors = + MultiSpanProcessorTestPeer::GetProcessors(processor_typeed); EXPECT_EQ(processors_raw, contained_processors); } From 7c58e6cf3a094fbfab92d87510f86c5758df9693 Mon Sep 17 00:00:00 2001 From: Jakob Lovhall Date: Fri, 15 May 2026 00:00:38 +0200 Subject: [PATCH 10/15] more formatting --- sdk/test/trace/tracer_provider_test.cc | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/sdk/test/trace/tracer_provider_test.cc b/sdk/test/trace/tracer_provider_test.cc index 4663c633d2..c2ad59b6ad 100644 --- a/sdk/test/trace/tracer_provider_test.cc +++ b/sdk/test/trace/tracer_provider_test.cc @@ -58,10 +58,9 @@ namespace trace class MultiSpanProcessorTestPeer { public: - static - std::vector GetProcessors(MultiSpanProcessor * multi_span_processor) + static std::vector GetProcessors(MultiSpanProcessor * multi_span_processor) { - std::vector res; + std::vector res; MultiSpanProcessor::ProcessorNode *node = multi_span_processor->head_; while (node != nullptr) @@ -74,8 +73,8 @@ class MultiSpanProcessorTestPeer return res; } }; -} -} +} // namespace trace +} // namespace sdk OPENTELEMETRY_END_NAMESPACE TEST(TracerProvider, GetTracer) @@ -405,7 +404,7 @@ TEST(TracerProvider, GetProcessorsTwo) ASSERT_NE(nullptr, processor_typeed); std::vector contained_processors = - MultiSpanProcessorTestPeer::GetProcessors(processor_typeed); + MultiSpanProcessorTestPeer::GetProcessors(processor_typeed); EXPECT_EQ(processors_raw, contained_processors); } @@ -438,7 +437,7 @@ TEST(TracerProvider, GetProcessorsThree) ASSERT_NE(nullptr, processor_typeed); std::vector contained_processors = - MultiSpanProcessorTestPeer::GetProcessors(processor_typeed); + MultiSpanProcessorTestPeer::GetProcessors(processor_typeed); EXPECT_EQ(processors_raw, contained_processors); } From 6377e5499dfebf44854e90f002910b26c77023ec Mon Sep 17 00:00:00 2001 From: Jakob Lovhall Date: Fri, 15 May 2026 00:02:00 +0200 Subject: [PATCH 11/15] format --- sdk/test/trace/tracer_provider_test.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/test/trace/tracer_provider_test.cc b/sdk/test/trace/tracer_provider_test.cc index c2ad59b6ad..0ae7767672 100644 --- a/sdk/test/trace/tracer_provider_test.cc +++ b/sdk/test/trace/tracer_provider_test.cc @@ -58,7 +58,7 @@ namespace trace class MultiSpanProcessorTestPeer { public: - static std::vector GetProcessors(MultiSpanProcessor * multi_span_processor) + static std::vector GetProcessors(MultiSpanProcessor *multi_span_processor) { std::vector res; From 75d829fefad6619644e98b69d0999be702d8b46e Mon Sep 17 00:00:00 2001 From: Jakob Lovhall Date: Thu, 11 Jun 2026 19:33:58 +0200 Subject: [PATCH 12/15] make span remember the SpanProcessor it was created with --- sdk/src/trace/span.cc | 10 ++++++++-- sdk/src/trace/span.h | 3 ++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/sdk/src/trace/span.cc b/sdk/src/trace/span.cc index d764540875..9c31930600 100644 --- a/sdk/src/trace/span.cc +++ b/sdk/src/trace/span.cc @@ -89,7 +89,11 @@ Span::Span(std::shared_ptr &&tracer, recordable_->SetStartTime(NowOr(options.start_system_time)); start_steady_time = NowOr(options.start_steady_time); recordable_->SetResource(tracer_->GetResource()); - tracer_->GetProcessor().OnStart(*recordable_, parent_span_context); + + // store the span processor, this is important to use the same processor even + // in case the tracer changes from single processor to a MultiSpanProcessor + span_processor_ = &tracer_->GetProcessor(); + span_processor_->OnStart(*recordable_, parent_span_context); } Span::~Span() @@ -203,6 +207,8 @@ void Span::End(const opentelemetry::trace::EndSpanOptions &options) noexcept { std::lock_guard lock_guard{mu_}; + // has_ended_ could be removed and instead rely on span_processor_, + // resetting it after calling OnEnd. it would save 8 bytes in each Span object. if (has_ended_ == true) { return; @@ -218,7 +224,7 @@ void Span::End(const opentelemetry::trace::EndSpanOptions &options) noexcept recordable_->SetDuration(std::chrono::steady_clock::time_point(end_steady_time) - std::chrono::steady_clock::time_point(start_steady_time)); - tracer_->GetProcessor().OnEnd(std::move(recordable_)); + span_processor_->OnEnd(std::move(recordable_)); recordable_.reset(); } diff --git a/sdk/src/trace/span.h b/sdk/src/trace/span.h index 2a5614821d..5adfa815d0 100644 --- a/sdk/src/trace/span.h +++ b/sdk/src/trace/span.h @@ -79,11 +79,12 @@ class Span final : public opentelemetry::trace::Span } private: - std::shared_ptr tracer_; + std::shared_ptr tracer_; // also keeps span_processor_ alive mutable std::mutex mu_; std::unique_ptr recordable_; opentelemetry::common::SteadyTimestamp start_steady_time; std::unique_ptr span_context_; + SpanProcessor * span_processor_{nullptr}; // kept alive by tracer_ bool has_ended_{false}; }; } // namespace trace From b7bfe4d328f46827ca2cb4de6b7c33ef8de74c81 Mon Sep 17 00:00:00 2001 From: Jakob Lovhall Date: Thu, 11 Jun 2026 19:42:45 +0200 Subject: [PATCH 13/15] formatting --- sdk/src/trace/span.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sdk/src/trace/span.h b/sdk/src/trace/span.h index 5adfa815d0..9d7929961c 100644 --- a/sdk/src/trace/span.h +++ b/sdk/src/trace/span.h @@ -79,12 +79,12 @@ class Span final : public opentelemetry::trace::Span } private: - std::shared_ptr tracer_; // also keeps span_processor_ alive + std::shared_ptr tracer_; // also keeps span_processor_ alive mutable std::mutex mu_; std::unique_ptr recordable_; opentelemetry::common::SteadyTimestamp start_steady_time; std::unique_ptr span_context_; - SpanProcessor * span_processor_{nullptr}; // kept alive by tracer_ + SpanProcessor *span_processor_{nullptr}; // kept alive by tracer_ bool has_ended_{false}; }; } // namespace trace From e43f22c505583b549cb2ca55030dcca79c4dea6d Mon Sep 17 00:00:00 2001 From: Jakob Lovhall Date: Thu, 11 Jun 2026 20:50:04 +0200 Subject: [PATCH 14/15] include what you use --- sdk/src/trace/span.h | 1 + 1 file changed, 1 insertion(+) diff --git a/sdk/src/trace/span.h b/sdk/src/trace/span.h index 9d7929961c..aed45af548 100644 --- a/sdk/src/trace/span.h +++ b/sdk/src/trace/span.h @@ -12,6 +12,7 @@ #include "opentelemetry/nostd/string_view.h" #include "opentelemetry/sdk/trace/recordable.h" #include "opentelemetry/sdk/trace/tracer.h" +#include "opentelemetry/sdk/trace/processor.h" #include "opentelemetry/trace/span.h" #include "opentelemetry/trace/span_context.h" #include "opentelemetry/trace/span_context_kv_iterable.h" From 6839cdaf7ec515b6c50632ffaf3085feec735983 Mon Sep 17 00:00:00 2001 From: Jakob Lovhall Date: Thu, 11 Jun 2026 20:55:36 +0200 Subject: [PATCH 15/15] format --- sdk/src/trace/span.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/src/trace/span.h b/sdk/src/trace/span.h index aed45af548..e9bd1fd88a 100644 --- a/sdk/src/trace/span.h +++ b/sdk/src/trace/span.h @@ -10,9 +10,9 @@ #include "opentelemetry/common/key_value_iterable.h" #include "opentelemetry/common/timestamp.h" #include "opentelemetry/nostd/string_view.h" +#include "opentelemetry/sdk/trace/processor.h" #include "opentelemetry/sdk/trace/recordable.h" #include "opentelemetry/sdk/trace/tracer.h" -#include "opentelemetry/sdk/trace/processor.h" #include "opentelemetry/trace/span.h" #include "opentelemetry/trace/span_context.h" #include "opentelemetry/trace/span_context_kv_iterable.h"