From 53566001bb73ac8069acd2b76559d2734a0b7ce4 Mon Sep 17 00:00:00 2001 From: Marc Alff Date: Sun, 22 Oct 2023 23:24:05 +0200 Subject: [PATCH] Add single link --- CHANGELOG.md | 3 +- api/include/opentelemetry/plugin/tracer.h | 10 +- .../opentelemetry/trace/default_span.h | 5 +- api/include/opentelemetry/trace/noop.h | 6 +- api/include/opentelemetry/trace/span.h | 55 ++++- examples/plugin/plugin/tracer.cc | 6 +- sdk/src/trace/span.cc | 18 +- sdk/src/trace/span.h | 5 +- sdk/test/trace/tracer_test.cc | 230 +++++++++++++++--- 9 files changed, 285 insertions(+), 53 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2043b0f472..ddc222bf3b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,7 +36,8 @@ Important changes: * [API] Add a new AddLink() operation to Span [#2380](https://github.com/open-telemetry/opentelemetry-cpp/pull/2380) - * new `API` Span::AddLink() adds links to a span. + * New `API` Span::AddLink() adds a single link to a span. + * New `API` Span::AddLinks() adds multiple links to a span. * Because this is an `ABI` breaking change, the fix is only available with the `CMake` option `WITH_ABI_VERSION_2=ON`. * When building with `CMake` option `WITH_ABI_VERSION_1=ON` (by default) diff --git a/api/include/opentelemetry/plugin/tracer.h b/api/include/opentelemetry/plugin/tracer.h index 6ca2228f29..068b08071d 100644 --- a/api/include/opentelemetry/plugin/tracer.h +++ b/api/include/opentelemetry/plugin/tracer.h @@ -51,9 +51,15 @@ class Span final : public trace::Span } #if OPENTELEMETRY_ABI_VERSION_NO >= 2 - void AddLink(const trace::SpanContextKeyValueIterable *links) noexcept override + void AddLink(const trace::SpanContext &target, + const common::KeyValueIterable &attrs) noexcept override { - span_->AddLink(links); + span_->AddLink(target, attrs); + } + + void AddLinks(const trace::SpanContextKeyValueIterable &links) noexcept override + { + span_->AddLinks(links); } #endif diff --git a/api/include/opentelemetry/trace/default_span.h b/api/include/opentelemetry/trace/default_span.h index 86d43ea5e1..3d0088de0d 100644 --- a/api/include/opentelemetry/trace/default_span.h +++ b/api/include/opentelemetry/trace/default_span.h @@ -48,7 +48,10 @@ class DefaultSpan : public Span {} #if OPENTELEMETRY_ABI_VERSION_NO >= 2 - void AddLink(const SpanContextKeyValueIterable * /* links */) noexcept override {} + void AddLink(const SpanContext & /* target */, + const common::KeyValueIterable & /* attrs */) noexcept override + {} + void AddLinks(const SpanContextKeyValueIterable & /* links */) noexcept override {} #endif void SetStatus(StatusCode /* status */, nostd::string_view /* description */) noexcept override {} diff --git a/api/include/opentelemetry/trace/noop.h b/api/include/opentelemetry/trace/noop.h index ca467298cf..407f3c1ac9 100644 --- a/api/include/opentelemetry/trace/noop.h +++ b/api/include/opentelemetry/trace/noop.h @@ -60,7 +60,11 @@ class OPENTELEMETRY_EXPORT NoopSpan final : public Span {} #if OPENTELEMETRY_ABI_VERSION_NO >= 2 - void AddLink(const SpanContextKeyValueIterable * /* links */) noexcept override {} + void AddLink(const SpanContext & /* target */, + const common::KeyValueIterable & /* attrs */) noexcept override + {} + + void AddLinks(const SpanContextKeyValueIterable & /* links */) noexcept override {} #endif void SetStatus(StatusCode /*code*/, nostd::string_view /*description*/) noexcept override {} diff --git a/api/include/opentelemetry/trace/span.h b/api/include/opentelemetry/trace/span.h index 7a7734dcdb..e7e9a679be 100644 --- a/api/include/opentelemetry/trace/span.h +++ b/api/include/opentelemetry/trace/span.h @@ -103,12 +103,53 @@ class Span #if OPENTELEMETRY_ABI_VERSION_NO >= 2 + /** + * Add link (ABI). + * + * @since ABI_VERSION 2 + */ + virtual void AddLink(const SpanContext &target, + const common::KeyValueIterable &attrs) noexcept = 0; + /** * Add links (ABI). * * @since ABI_VERSION 2 */ - virtual void AddLink(const SpanContextKeyValueIterable *links) noexcept = 0; + virtual void AddLinks(const SpanContextKeyValueIterable &links) noexcept = 0; + + /** + * Add link (API helper). + * + * @since ABI_VERSION 2 + */ + template ::value> * = nullptr> + void AddLink(const SpanContext &target, const U &attrs) + { + common::KeyValueIterableView view(attrs); + this->AddLink(target, view); + } + + /** + * Add link (API helper). + * + * @since ABI_VERSION 2 + */ + void AddLink(const SpanContext &target, + std::initializer_list> attrs) + { + /* Build a container from std::initializer_list. */ + nostd::span> container{ + attrs.begin(), attrs.end()}; + + /* Build a view on the container. */ + common::KeyValueIterableView< + nostd::span>> + view(container); + + return this->AddLink(target, view); + } /** * Add links (API helper). @@ -116,10 +157,10 @@ class Span * @since ABI_VERSION 2 */ template ::value> * = nullptr> - void AddLink(const U &links) + void AddLinks(const U &links) { SpanContextKeyValueIterableView view(links); - this->AddLink(&view); + this->AddLinks(view); } /** @@ -127,7 +168,7 @@ class Span * * @since ABI_VERSION 2 */ - void AddLink( + void AddLinks( std::initializer_list< std::pair>>> @@ -136,14 +177,14 @@ class Span /* Build a container from std::initializer_list. */ nostd::span>>> - links_span{links.begin(), links.end()}; + container{links.begin(), links.end()}; /* Build a view on the container. */ SpanContextKeyValueIterableView>>>> - view(links_span); + view(container); - return this->AddLink(&view); + return this->AddLinks(view); } #endif /* OPENTELEMETRY_ABI_VERSION_NO */ diff --git a/examples/plugin/plugin/tracer.cc b/examples/plugin/plugin/tracer.cc index e24056c117..9579d0204e 100644 --- a/examples/plugin/plugin/tracer.cc +++ b/examples/plugin/plugin/tracer.cc @@ -50,7 +50,11 @@ class Span final : public trace::Span {} #if OPENTELEMETRY_ABI_VERSION_NO >= 2 - void AddLink(const trace::SpanContextKeyValueIterable * /* links */) noexcept override {} + void AddLink(const trace::SpanContext &target, + const common::KeyValueIterable &attrs) noexcept override + {} + + void AddLinks(const trace::SpanContextKeyValueIterable & /* links */) noexcept override {} #endif void SetStatus(trace::StatusCode /*code*/, nostd::string_view /*description*/) noexcept override diff --git a/sdk/src/trace/span.cc b/sdk/src/trace/span.cc index eef67e82d6..25708cddd9 100644 --- a/sdk/src/trace/span.cc +++ b/sdk/src/trace/span.cc @@ -147,7 +147,8 @@ void Span::AddEvent(nostd::string_view name, } #if OPENTELEMETRY_ABI_VERSION_NO >= 2 -void Span::AddLink(const opentelemetry::trace::SpanContextKeyValueIterable *links) noexcept +void Span::AddLink(const opentelemetry::trace::SpanContext &target, + const opentelemetry::common::KeyValueIterable &attrs) noexcept { std::lock_guard lock_guard{mu_}; if (recordable_ == nullptr) @@ -155,8 +156,19 @@ void Span::AddLink(const opentelemetry::trace::SpanContextKeyValueIterable *link return; } - links->ForEachKeyValue([&](opentelemetry::trace::SpanContext span_context, - const common::KeyValueIterable &attributes) { + recordable_->AddLink(target, attrs); +} + +void Span::AddLinks(const opentelemetry::trace::SpanContextKeyValueIterable &links) noexcept +{ + std::lock_guard lock_guard{mu_}; + if (recordable_ == nullptr) + { + return; + } + + links.ForEachKeyValue([&](opentelemetry::trace::SpanContext span_context, + const common::KeyValueIterable &attributes) { recordable_->AddLink(span_context, attributes); return true; }); diff --git a/sdk/src/trace/span.h b/sdk/src/trace/span.h index c49b204443..bd255b86b6 100644 --- a/sdk/src/trace/span.h +++ b/sdk/src/trace/span.h @@ -46,7 +46,10 @@ class Span final : public opentelemetry::trace::Span nostd::string_view description) noexcept override; #if OPENTELEMETRY_ABI_VERSION_NO >= 2 - void AddLink(const opentelemetry::trace::SpanContextKeyValueIterable *links) noexcept override; + void AddLink(const opentelemetry::trace::SpanContext &target, + const opentelemetry::common::KeyValueIterable &attrs) noexcept override; + + void AddLinks(const opentelemetry::trace::SpanContextKeyValueIterable &links) noexcept override; #endif void UpdateName(nostd::string_view name) noexcept override; diff --git a/sdk/test/trace/tracer_test.cc b/sdk/test/trace/tracer_test.cc index 5013598b5b..2dd9ace86b 100644 --- a/sdk/test/trace/tracer_test.cc +++ b/sdk/test/trace/tracer_test.cc @@ -519,6 +519,113 @@ TEST(Tracer, SpanSetLinks) } } +#if OPENTELEMETRY_ABI_VERSION_NO >= 2 +TEST(Tracer, SpanAddLinkAbiv2) +{ + InMemorySpanExporter *exporter = new InMemorySpanExporter(); + std::shared_ptr span_data = exporter->GetData(); + auto tracer = initTracer(std::unique_ptr{exporter}); + + { + auto span = tracer->StartSpan("span"); + SpanContext target(false, false); + // Single link attribute passed through Initialization list + span->AddLink(target, {{"attr2", 2}}); + span->End(); + + auto spans = span_data->GetSpans(); + ASSERT_EQ(1, spans.size()); + + auto &span_data_links = spans.at(0)->GetLinks(); + ASSERT_EQ(1, span_data_links.size()); + auto link = span_data_links.at(0); + auto attrs = link.GetAttributes(); + ASSERT_EQ(nostd::get(attrs.at("attr2")), 2); + } + + { + auto span = tracer->StartSpan("span"); + SpanContext target(false, false); + // Multiple link attributes passed through Initialization list + span->AddLink(target, {{"attr2", 2}, {"attr3", 3}}); + span->End(); + + auto spans = span_data->GetSpans(); + ASSERT_EQ(1, spans.size()); + + auto &span_data_links = spans.at(0)->GetLinks(); + ASSERT_EQ(1, span_data_links.size()); + auto link = span_data_links.at(0); + auto attrs = link.GetAttributes(); + ASSERT_EQ(nostd::get(attrs.at("attr2")), 2); + ASSERT_EQ(nostd::get(attrs.at("attr3")), 3); + } + + { + std::map attrs_map = {{"attr1", "1"}, {"attr2", "2"}}; + + auto span = tracer->StartSpan("span"); + SpanContext target(false, false); + span->AddLink(target, attrs_map); + span->End(); + + auto spans = span_data->GetSpans(); + + auto &span_data_links = spans.at(0)->GetLinks(); + ASSERT_EQ(1, span_data_links.size()); + auto link = span_data_links.at(0); + auto attrs = link.GetAttributes(); + ASSERT_EQ(nostd::get(attrs.at("attr1")), "1"); + ASSERT_EQ(nostd::get(attrs.at("attr2")), "2"); + } + + { + auto span = tracer->StartSpan("span"); + SpanContext target(false, false); + + // Single link attribute passed through Initialization list + span->AddLink(target, {{"attr1", 1}}); + + // Multiple link attributes passed through Initialization list + span->AddLink(target, {{"attr2", 2}, {"attr3", 3}}); + + std::map attrs_map = {{"attr4", "4"}, {"attr5", "5"}}; + span->AddLink(target, attrs_map); + + span->End(); + + auto spans = span_data->GetSpans(); + ASSERT_EQ(1, spans.size()); + + auto &span_data_links = spans.at(0)->GetLinks(); + ASSERT_EQ(3, span_data_links.size()); + + { + auto link = span_data_links.at(0); + auto attrs = link.GetAttributes(); + ASSERT_EQ(attrs.size(), 1); + ASSERT_EQ(nostd::get(attrs.at("attr1")), 1); + } + + { + auto link = span_data_links.at(1); + auto attrs = link.GetAttributes(); + ASSERT_EQ(attrs.size(), 2); + ASSERT_EQ(nostd::get(attrs.at("attr2")), 2); + ASSERT_EQ(nostd::get(attrs.at("attr3")), 3); + } + + { + auto link = span_data_links.at(2); + auto attrs = link.GetAttributes(); + ASSERT_EQ(attrs.size(), 2); + ASSERT_EQ(nostd::get(attrs.at("attr4")), "4"); + ASSERT_EQ(nostd::get(attrs.at("attr5")), "5"); + } + } +} +#endif /* OPENTELEMETRY_ABI_VERSION_NO >= 2 */ + #if OPENTELEMETRY_ABI_VERSION_NO >= 2 TEST(Tracer, SpanAddLinksAbiv2) { @@ -527,9 +634,9 @@ TEST(Tracer, SpanAddLinksAbiv2) auto tracer = initTracer(std::unique_ptr{exporter}); { - auto span = tracer->StartSpan("span 1"); + auto span = tracer->StartSpan("span"); // Single span link passed through Initialization list - span->AddLink({{SpanContext(false, false), {{"attr2", 2}}}}); + span->AddLinks({{SpanContext(false, false), {{"attr2", 2}}}}); span->End(); auto spans = span_data->GetSpans(); @@ -542,9 +649,9 @@ TEST(Tracer, SpanAddLinksAbiv2) } { - auto span = tracer->StartSpan("span 2"); + auto span = tracer->StartSpan("span"); // Multiple span links passed through Initialization list - span->AddLink( + span->AddLinks( {{SpanContext(false, false), {{"attr2", 2}}}, {SpanContext(false, false), {{"attr3", 3}}}}); span->End(); @@ -560,10 +667,10 @@ TEST(Tracer, SpanAddLinksAbiv2) } { - auto span = tracer->StartSpan("span 3"); + auto span = tracer->StartSpan("span"); // Multiple links, each with multiple attributes passed through Initialization list - span->AddLink({{SpanContext(false, false), {{"attr2", 2}, {"attr3", 3}}}, - {SpanContext(false, false), {{"attr4", 4}}}}); + span->AddLinks({{SpanContext(false, false), {{"attr2", 2}, {"attr3", 3}}}, + {SpanContext(false, false), {{"attr4", 4}}}}); span->End(); auto spans = span_data->GetSpans(); @@ -585,8 +692,8 @@ TEST(Tracer, SpanAddLinksAbiv2) std::vector>> links = { {SpanContext(false, false), attrs1}, {SpanContext(false, false), attrs2}}; - auto span = tracer->StartSpan("span 4"); - span->AddLink(links); + auto span = tracer->StartSpan("span"); + span->AddLinks(links); span->End(); auto spans = span_data->GetSpans(); @@ -602,23 +709,23 @@ TEST(Tracer, SpanAddLinksAbiv2) } { - auto span = tracer->StartSpan("span 5"); + auto span = tracer->StartSpan("span"); // Single span link passed through Initialization list - span->AddLink({{SpanContext(false, false), {{"attr10", 10}}}}); - span->AddLink({{SpanContext(false, false), {{"attr11", 11}}}}); + span->AddLinks({{SpanContext(false, false), {{"attr10", 10}}}}); + span->AddLinks({{SpanContext(false, false), {{"attr11", 11}}}}); // Multiple span links passed through Initialization list - span->AddLink({{SpanContext(false, false), {{"attr12", 12}}}, - {SpanContext(false, false), {{"attr13", 13}}}}); - span->AddLink({{SpanContext(false, false), {{"attr14", 14}}}, - {SpanContext(false, false), {{"attr15", 15}}}}); + span->AddLinks({{SpanContext(false, false), {{"attr12", 12}}}, + {SpanContext(false, false), {{"attr13", 13}}}}); + span->AddLinks({{SpanContext(false, false), {{"attr14", 14}}}, + {SpanContext(false, false), {{"attr15", 15}}}}); // Multiple links, each with multiple attributes passed through Initialization list - span->AddLink({{SpanContext(false, false), {{"attr16", 16}, {"attr17", 17}}}, - {SpanContext(false, false), {{"attr18", 18}}}}); - span->AddLink({{SpanContext(false, false), {{"attr19", 19}, {"attr20", 20}}}, - {SpanContext(false, false), {{"attr21", 21}}}}); + span->AddLinks({{SpanContext(false, false), {{"attr16", 16}, {"attr17", 17}}}, + {SpanContext(false, false), {{"attr18", 18}}}}); + span->AddLinks({{SpanContext(false, false), {{"attr19", 19}, {"attr20", 20}}}, + {SpanContext(false, false), {{"attr21", 21}}}}); std::map attrsa1 = {{"attra1", "1"}, {"attra2", "2"}}; std::map attrsa2 = {{"attra3", "3"}, {"attra4", "4"}}; @@ -626,7 +733,7 @@ TEST(Tracer, SpanAddLinksAbiv2) std::vector>> linksa = { {SpanContext(false, false), attrsa1}, {SpanContext(false, false), attrsa2}}; - span->AddLink(linksa); + span->AddLinks(linksa); std::map attrsb1 = {{"attrb1", "1"}, {"attrb2", "2"}}; std::map attrsb2 = {{"attrb3", "3"}, {"attrb4", "4"}}; @@ -634,7 +741,7 @@ TEST(Tracer, SpanAddLinksAbiv2) std::vector>> linksb = { {SpanContext(false, false), attrsb1}, {SpanContext(false, false), attrsb2}}; - span->AddLink(linksb); + span->AddLinks(linksb); span->End(); @@ -645,49 +752,49 @@ TEST(Tracer, SpanAddLinksAbiv2) ASSERT_EQ(14, span_data_links.size()); { - auto link = span_data_links.at(0); + auto link = span_data_links.at(0); auto attrs = link.GetAttributes(); ASSERT_EQ(attrs.size(), 1); ASSERT_EQ(nostd::get(attrs.at("attr10")), 10); } { - auto link = span_data_links.at(1); + auto link = span_data_links.at(1); auto attrs = link.GetAttributes(); ASSERT_EQ(attrs.size(), 1); ASSERT_EQ(nostd::get(attrs.at("attr11")), 11); } { - auto link = span_data_links.at(2); + auto link = span_data_links.at(2); auto attrs = link.GetAttributes(); ASSERT_EQ(attrs.size(), 1); ASSERT_EQ(nostd::get(attrs.at("attr12")), 12); } { - auto link = span_data_links.at(3); + auto link = span_data_links.at(3); auto attrs = link.GetAttributes(); ASSERT_EQ(attrs.size(), 1); ASSERT_EQ(nostd::get(attrs.at("attr13")), 13); } { - auto link = span_data_links.at(4); + auto link = span_data_links.at(4); auto attrs = link.GetAttributes(); ASSERT_EQ(attrs.size(), 1); ASSERT_EQ(nostd::get(attrs.at("attr14")), 14); } { - auto link = span_data_links.at(5); + auto link = span_data_links.at(5); auto attrs = link.GetAttributes(); ASSERT_EQ(attrs.size(), 1); ASSERT_EQ(nostd::get(attrs.at("attr15")), 15); } { - auto link = span_data_links.at(6); + auto link = span_data_links.at(6); auto attrs = link.GetAttributes(); ASSERT_EQ(attrs.size(), 2); ASSERT_EQ(nostd::get(attrs.at("attr16")), 16); @@ -695,14 +802,14 @@ TEST(Tracer, SpanAddLinksAbiv2) } { - auto link = span_data_links.at(7); + auto link = span_data_links.at(7); auto attrs = link.GetAttributes(); ASSERT_EQ(attrs.size(), 1); ASSERT_EQ(nostd::get(attrs.at("attr18")), 18); } { - auto link = span_data_links.at(8); + auto link = span_data_links.at(8); auto attrs = link.GetAttributes(); ASSERT_EQ(attrs.size(), 2); ASSERT_EQ(nostd::get(attrs.at("attr19")), 19); @@ -710,14 +817,14 @@ TEST(Tracer, SpanAddLinksAbiv2) } { - auto link = span_data_links.at(9); + auto link = span_data_links.at(9); auto attrs = link.GetAttributes(); ASSERT_EQ(attrs.size(), 1); ASSERT_EQ(nostd::get(attrs.at("attr21")), 21); } { - auto link = span_data_links.at(10); + auto link = span_data_links.at(10); auto attrs = link.GetAttributes(); ASSERT_EQ(attrs.size(), 2); ASSERT_EQ(nostd::get(attrs.at("attra1")), "1"); @@ -725,7 +832,7 @@ TEST(Tracer, SpanAddLinksAbiv2) } { - auto link = span_data_links.at(11); + auto link = span_data_links.at(11); auto attrs = link.GetAttributes(); ASSERT_EQ(attrs.size(), 2); ASSERT_EQ(nostd::get(attrs.at("attra3")), "3"); @@ -733,7 +840,7 @@ TEST(Tracer, SpanAddLinksAbiv2) } { - auto link = span_data_links.at(12); + auto link = span_data_links.at(12); auto attrs = link.GetAttributes(); ASSERT_EQ(attrs.size(), 2); ASSERT_EQ(nostd::get(attrs.at("attrb1")), "1"); @@ -741,7 +848,7 @@ TEST(Tracer, SpanAddLinksAbiv2) } { - auto link = span_data_links.at(13); + auto link = span_data_links.at(13); auto attrs = link.GetAttributes(); ASSERT_EQ(attrs.size(), 2); ASSERT_EQ(nostd::get(attrs.at("attrb3")), "3"); @@ -751,6 +858,57 @@ TEST(Tracer, SpanAddLinksAbiv2) } #endif /* OPENTELEMETRY_ABI_VERSION_NO >= 2 */ +#if OPENTELEMETRY_ABI_VERSION_NO >= 2 +TEST(Tracer, SpanMixLinksAbiv2) +{ + InMemorySpanExporter *exporter = new InMemorySpanExporter(); + std::shared_ptr span_data = exporter->GetData(); + auto tracer = initTracer(std::unique_ptr{exporter}); + + { + // Link 1 added at StartSpan + auto span = + tracer->StartSpan("span", {{"attr1", 1}}, {{SpanContext(false, false), {{"attr2", 2}}}}); + + SpanContext target(false, false); + // Link 2 added with AddLink + span->AddLink(target, {{"attr3", 3}}); + + // Link 3 added with AddLinks + span->AddLinks({{SpanContext(false, false), {{"attr4", 4}}}}); + + span->End(); + + auto spans = span_data->GetSpans(); + ASSERT_EQ(1, spans.size()); + + auto &span_data_links = spans.at(0)->GetLinks(); + ASSERT_EQ(3, span_data_links.size()); + + { + auto link = span_data_links.at(0); + auto attrs = link.GetAttributes(); + ASSERT_EQ(attrs.size(), 1); + ASSERT_EQ(nostd::get(attrs.at("attr2")), 2); + } + + { + auto link = span_data_links.at(1); + auto attrs = link.GetAttributes(); + ASSERT_EQ(attrs.size(), 1); + ASSERT_EQ(nostd::get(attrs.at("attr3")), 3); + } + + { + auto link = span_data_links.at(2); + auto attrs = link.GetAttributes(); + ASSERT_EQ(attrs.size(), 1); + ASSERT_EQ(nostd::get(attrs.at("attr4")), 4); + } + } +} +#endif /* OPENTELEMETRY_ABI_VERSION_NO >= 2 */ + TEST(Tracer, TestAlwaysOnSampler) { InMemorySpanExporter *exporter = new InMemorySpanExporter();