-
Notifications
You must be signed in to change notification settings - Fork 567
[SDK] Do not use MultiSpanProcessor for single processors #4043
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
a553411
c6b2bca
18a46c7
4a21219
9be6481
c74712f
8470609
fc50aae
8591d82
739e24e
6a785f5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -13,6 +13,7 @@ | |
| #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" | ||
|
|
@@ -38,6 +39,33 @@ | |
| using namespace opentelemetry::sdk::trace; | ||
| using namespace opentelemetry::sdk::resource; | ||
|
|
||
| OPENTELEMETRY_BEGIN_NAMESPACE | ||
| namespace sdk | ||
| { | ||
| namespace trace | ||
| { | ||
| class MultiSpanProcessorTestPeer | ||
| { | ||
| public: | ||
| static std::vector<SpanProcessor *> GetProcessors(MultiSpanProcessor *multi_span_processor) | ||
| { | ||
| std::vector<SpanProcessor *> 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; | ||
| } | ||
| }; | ||
| } // namespace trace | ||
| } // namespace sdk | ||
| OPENTELEMETRY_END_NAMESPACE | ||
|
|
||
| TEST(TracerProvider, GetTracer) | ||
| { | ||
| std::unique_ptr<SpanProcessor> processor(new SimpleSpanProcessor(nullptr)); | ||
|
|
@@ -318,6 +346,90 @@ 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<SpanProcessor> processor(new SimpleSpanProcessor(nullptr)); | ||
| std::vector<std::unique_ptr<SpanProcessor>> processors; | ||
| processors.push_back(std::move(processor)); | ||
|
|
||
| std::unique_ptr<TracerContext> 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<SimpleSpanProcessor *>(&span_processor); | ||
| #else | ||
| auto processor_typeed = static_cast<SimpleSpanProcessor *>(&span_processor); | ||
| #endif | ||
| ASSERT_NE(nullptr, processor_typeed); | ||
| } | ||
|
|
||
| // get a MultiSpanProcessor back that wraps both processors | ||
| TEST(TracerProvider, GetProcessorsTwo) | ||
| { | ||
| std::vector<SpanProcessor *> 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<SpanProcessor> processor1(processors_raw[0]); | ||
| std::unique_ptr<SpanProcessor> processor2(processors_raw[1]); | ||
|
|
||
| std::vector<std::unique_ptr<SpanProcessor>> processors; | ||
| processors.push_back(std::move(processor1)); | ||
| processors.push_back(std::move(processor2)); | ||
|
|
||
| std::unique_ptr<TracerContext> 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<MultiSpanProcessor *>(&span_processor); | ||
| #else | ||
| auto processor_typeed = static_cast<MultiSpanProcessor *>(&span_processor); | ||
| #endif | ||
| ASSERT_NE(nullptr, processor_typeed); | ||
|
|
||
| std::vector<SpanProcessor *> 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<SpanProcessor *> 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<SpanProcessor> processor1(processors_raw[0]); | ||
| std::unique_ptr<SpanProcessor> processor2(processors_raw[1]); | ||
| std::unique_ptr<SpanProcessor> processor3(processors_raw[2]); | ||
| std::vector<std::unique_ptr<SpanProcessor>> processors; | ||
| processors.push_back(std::move(processor1)); | ||
| processors.push_back(std::move(processor2)); | ||
| processors.push_back(std::move(processor3)); | ||
|
|
||
| std::unique_ptr<TracerContext> 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<MultiSpanProcessor *>(&span_processor); | ||
| #else | ||
| auto processor_typeed = static_cast<MultiSpanProcessor *>(&span_processor); | ||
| #endif | ||
| ASSERT_NE(nullptr, processor_typeed); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Shoule we check
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes, but how?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We can add friend class only for test, like OtlpHttpExporterTestPeer in exporters/otlp/include/opentelemetry/exporters/otlp/otlp_http_exporter.h and exporters/otlp/test/otlp_http_exporter_test.cc |
||
|
|
||
| std::vector<SpanProcessor *> contained_processors = | ||
| MultiSpanProcessorTestPeer::GetProcessors(processor_typeed); | ||
| EXPECT_EQ(processors_raw, contained_processors); | ||
| } | ||
|
|
||
| TEST(TracerProvider, Shutdown) | ||
| { | ||
| std::unique_ptr<SpanProcessor> processor(new SimpleSpanProcessor(nullptr)); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this break spans that were already started before
AddProcessor()runs? Those spans keep the recordable created by the old single processor, but after this lineSpan::End()will callMultiSpanProcessor::OnEnd(), which expects aMultiRecordable. Maybe promotion needs to preserve the old processor path for existing spans.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hmm. yes I agree that it breaks currently live spans in they way you describe. unfortunate. do you have a suggestion on how to get around this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe the cleanest fix is for
Spanto remember the processor used when it was started.That should not require shared ownership or another heap allocation per span. It could just store a raw
SpanProcessor*captured at start, then use that same processor forOnEnd(). The span already keeps the tracer/context alive, so the processor lifetime should still be covered.