From: Pieter Lexis Date: Fri, 31 Oct 2025 13:35:21 +0000 (+0100) Subject: feat(dnsdist): Speed up adding Spans in the Tracer X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=0d4d945c5aba810193e35ab198d5975f8ab8f92b;p=thirdparty%2Fpdns.git feat(dnsdist): Speed up adding Spans in the Tracer This makes the code cleaner, and does away with the pre- and post-activation spans. We now have a "mini" span that we convert to actual Spans only when they need to be sent out. Using microbenchmarks the following became clear: Adding a Span to the Tracer (using `Closer::openSpan`) is now about 45% slower than adding it to an old "unactivated" Tracer. But is is *twice* as fast compared to the old "activated" Tracer. When tracing is enabled for a query, most spans are added *after* "activation". So this commit should speed up query processing when tracing is enabled. One downside of this commit is that generating the actual OpenTelemetry Trace data we now need to create the real Spans, this generation is about 60% slower. However, when the `delay` option is used for the RemoteLogResponseAction this slowness is not in the hot path of the query. As this generation happens after the response has been sent. Signed-off-by: Pieter Lexis --- diff --git a/pdns/dnsdistdist/dnsdist-actions-factory.cc b/pdns/dnsdistdist/dnsdist-actions-factory.cc index 28af79c4ef..34cc53994d 100644 --- a/pdns/dnsdistdist/dnsdist-actions-factory.cc +++ b/pdns/dnsdistdist/dnsdist-actions-factory.cc @@ -1692,15 +1692,11 @@ public: return Action::None; } if (d_value) { - tracer->activate(); tracer->setRootSpanAttribute("query.qname", AnyValue{dnsquestion->ids.qname.toStringNoDot()}); tracer->setRootSpanAttribute("query.qtype", AnyValue{QType(dnsquestion->ids.qtype).toString()}); tracer->setRootSpanAttribute("query.remote.address", AnyValue{dnsquestion->ids.origRemote.toString()}); tracer->setRootSpanAttribute("query.remote.port", AnyValue{dnsquestion->ids.origRemote.getPort()}); } - else { - tracer->deactivate(); - } dnsquestion->ids.tracingEnabled = d_value; #endif return Action::None; diff --git a/pdns/dnsdistdist/dnsdist-opentelemetry.cc b/pdns/dnsdistdist/dnsdist-opentelemetry.cc index 6813adfd99..0797d7fed5 100644 --- a/pdns/dnsdistdist/dnsdist-opentelemetry.cc +++ b/pdns/dnsdistdist/dnsdist-opentelemetry.cc @@ -56,38 +56,21 @@ TracesData Tracer::getTracesData() otTrace.resource_spans.at(0).scope_spans.at(0).scope.attributes.push_back(hostnameAttr); - { - auto lockedPre = d_preActivationSpans.read_only_lock(); - - for (auto const& preActivationTrace : *lockedPre) { - otTrace.resource_spans.at(0).scope_spans.at(0).spans.push_back( - { - .trace_id = d_traceid, - .span_id = preActivationTrace.span_id, - .parent_span_id = preActivationTrace.parent_span_id, - .name = preActivationTrace.name, - .kind = pdns::trace::Span::SpanKind::SPAN_KIND_SERVER, - .start_time_unix_nano = preActivationTrace.start_time_unix_nano, - .end_time_unix_nano = preActivationTrace.end_time_unix_nano, - }); - - if (preActivationTrace.parent_span_id == pdns::trace::s_emptySpanID) { - // This is the root span - otTrace.resource_spans.at(0).scope_spans.at(0).spans.back().attributes.insert( - otTrace.resource_spans.at(0).scope_spans.at(0).spans.back().attributes.cend(), - d_rootSpanAttributes.begin(), - d_rootSpanAttributes.end()); - } - } + auto lockedSpans = d_spans.read_only_lock(); + for (auto const& lockedSpan : *lockedSpans) { + otTrace.resource_spans.at(0).scope_spans.at(0).spans.push_back( + { + .trace_id = getTraceID(), + .span_id = lockedSpan.span_id, + .parent_span_id = lockedSpan.parent_span_id, + .name = lockedSpan.name, + .kind = pdns::trace::Span::SpanKind::SPAN_KIND_SERVER, + .start_time_unix_nano = lockedSpan.start_time_unix_nano, + .end_time_unix_nano = lockedSpan.end_time_unix_nano, + .attributes = lockedSpan.attributes, + }); } - { - auto lockedPost = d_postActivationSpans.read_only_lock(); - otTrace.resource_spans.at(0).scope_spans.at(0).spans.insert( - otTrace.resource_spans.at(0).scope_spans.at(0).spans.end(), - lockedPost->begin(), - lockedPost->end()); - } return otTrace; #endif } @@ -117,29 +100,16 @@ SpanID Tracer::addSpan([[maybe_unused]] const std::string& name, [[maybe_unused] return 0; #else auto spanID = pdns::trace::SpanID::getRandomSpanID(); - if (d_activated) { - d_postActivationSpans.lock()->push_back({ - .trace_id = d_traceid, - .span_id = spanID, - .parent_span_id = parentSpanID, - .name = name, - .kind = pdns::trace::Span::SpanKind::SPAN_KIND_SERVER, - .start_time_unix_nano = pdns::trace::timestamp(), - }); - return spanID; - } - - // We're not activated, so we are in pre-activation. - d_preActivationSpans.lock()->push_back({ + d_spans.lock()->push_back({ .name = name, .span_id = spanID, .parent_span_id = parentSpanID, .start_time_unix_nano = pdns::trace::timestamp(), .end_time_unix_nano = 0, + .attributes = {}, }); d_lastSpanID = spanID; - return spanID; #endif } @@ -151,9 +121,6 @@ bool Tracer::setTraceAttribute([[maybe_unused]] const std::string& key, [[maybe_ // always succesfull return true; #else - if (!d_activated) { - return false; - } d_attributes.push_back({key, value}); return true; #endif @@ -162,26 +129,12 @@ bool Tracer::setTraceAttribute([[maybe_unused]] const std::string& key, [[maybe_ void Tracer::closeSpan([[maybe_unused]] const SpanID& spanID) { #ifndef DISABLE_PROTOBUF - if (d_activated) { - auto lockedPost = d_postActivationSpans.lock(); - auto spanIt = std::find_if( - lockedPost->rbegin(), - lockedPost->rend(), - [spanID](const pdns::trace::Span& span) { return span.span_id == spanID; }); - if (spanIt != lockedPost->rend()) { - if (spanIt->end_time_unix_nano == 0) { - spanIt->end_time_unix_nano = pdns::trace::timestamp(); - } - return; - } - } - - auto lockedPre = d_preActivationSpans.lock(); + auto lockedSpans = d_spans.lock(); auto spanIt = std::find_if( - lockedPre->rbegin(), - lockedPre->rend(), - [spanID](const preActivationSpanInfo& span) { return span.span_id == spanID; }); - if (spanIt != lockedPre->rend() && spanIt->end_time_unix_nano == 0) { + lockedSpans->rbegin(), + lockedSpans->rend(), + [spanID](const miniSpan& span) { return span.span_id == spanID; }); + if (spanIt != lockedSpans->rend() && spanIt->end_time_unix_nano == 0) { spanIt->end_time_unix_nano = pdns::trace::timestamp(); return; } @@ -191,10 +144,7 @@ void Tracer::closeSpan([[maybe_unused]] const SpanID& spanID) void Tracer::setRootSpanAttribute([[maybe_unused]] const std::string& key, [[maybe_unused]] const AnyValue& value) { #ifndef DISABLE_PROTOBUF - d_rootSpanAttributes.push_back({ - .key = key, - .value = value, - }); + setSpanAttribute(getRootSpanID(), key, value); #endif } @@ -202,17 +152,13 @@ void Tracer::setRootSpanAttribute([[maybe_unused]] const std::string& key, [[may void Tracer::setSpanAttribute([[maybe_unused]] const SpanID& spanid, [[maybe_unused]] const std::string& key, [[maybe_unused]] const AnyValue& value) { #ifndef DISABLE_PROTOBUF - if (d_activated) { - auto lockedPost = d_postActivationSpans.lock(); - if (auto iter = std::find_if(lockedPost->rbegin(), - lockedPost->rend(), - [spanid](const pdns::trace::Span& span) { return span.span_id == spanid; }); - iter != lockedPost->rend()) { - iter->attributes.push_back({key, value}); - return; - } + auto lockedSpans = d_spans.lock(); + if (auto iter = std::find_if(lockedSpans->rbegin(), + lockedSpans->rend(), + [spanid](const auto& span) { return span.span_id == spanid; }); + iter != lockedSpans->rend()) { + iter->attributes.push_back({key, value}); } - // XXX: It is not possible to add attributes to d_preActivationTraces. Perhaps these should be converted on calling activate #endif } @@ -221,7 +167,7 @@ SpanID Tracer::getRootSpanID() #ifdef DISABLE_PROTOBUF return 0; #else - if (auto spans = d_preActivationSpans.read_only_lock(); spans->size() != 0) { + if (auto spans = d_spans.read_only_lock(); !spans->empty()) { auto iter = std::find_if(spans->cbegin(), spans->cend(), [](const auto& span) { return span.parent_span_id == pdns::trace::s_emptySpanID; }); if (iter != spans->cend()) { return iter->span_id; @@ -236,13 +182,10 @@ SpanID Tracer::getLastSpanID() #ifdef DISABLE_PROTOBUF return 0; #else - if (d_activated && d_postActivationSpans.read_only_lock()->size() != 0) { - return d_postActivationSpans.read_only_lock()->back().span_id; - } - if (d_preActivationSpans.read_only_lock()->size() != 0) { - return d_preActivationSpans.read_only_lock()->back().span_id; + if (auto lockedSpans = d_spans.read_only_lock(); !lockedSpans->empty()) { + return lockedSpans->back().span_id; } - return SpanID{}; + return pdns::trace::s_emptySpanID; #endif } @@ -251,26 +194,15 @@ SpanID Tracer::getLastSpanIDForName([[maybe_unused]] const std::string& name) #ifdef DISABLE_PROTOBUF return 0; #else - if (d_activated && d_postActivationSpans.read_only_lock()->size() != 0) { - auto lockedPost = d_postActivationSpans.read_only_lock(); - if (auto iter = std::find_if(lockedPost->rbegin(), - lockedPost->rend(), - [name](const pdns::trace::Span& span) { return span.name == name; }); - iter != lockedPost->rend()) { - return iter->span_id; - } - } - - if (d_preActivationSpans.read_only_lock()->size() != 0) { - auto lockedPre = d_preActivationSpans.read_only_lock(); - if (auto iter = std::find_if(lockedPre->rbegin(), - lockedPre->rend(), - [name](const preActivationSpanInfo& span) { return span.name == name; }); - iter != lockedPre->rend()) { + if (auto lockedSpans = d_spans.read_only_lock(); !lockedSpans->empty()) { + if (auto iter = std::find_if(lockedSpans->rbegin(), + lockedSpans->rend(), + [name](const miniSpan& span) { return span.name == name; }); + iter != lockedSpans->rend()) { return iter->span_id; } } - return SpanID{}; + return pdns::trace::s_emptySpanID; #endif } @@ -279,6 +211,9 @@ TraceID Tracer::getTraceID() const #ifdef DISABLE_PROTOBUF return 0; #else + if (d_traceid == pdns::trace::s_emptyTraceID) { + d_traceid.makeRandom(); + } return d_traceid; #endif } diff --git a/pdns/dnsdistdist/dnsdist-opentelemetry.hh b/pdns/dnsdistdist/dnsdist-opentelemetry.hh index f3d5d27292..a13bfd0715 100644 --- a/pdns/dnsdistdist/dnsdist-opentelemetry.hh +++ b/pdns/dnsdistdist/dnsdist-opentelemetry.hh @@ -79,38 +79,9 @@ public: return std::shared_ptr(new Tracer); } - /** - * @brief Activate the Tracer - * - * Once activated, all new events are stored as actual Spans - */ - void activate() - { -#ifndef DISABLE_PROTOBUF - d_activated = true; - if (d_traceid == pdns::trace::s_emptyTraceID) { - d_traceid.makeRandom(); - } -#endif - } - - /** - * @brief Deactivate the tracer - */ - void deactivate() - { -#ifndef DISABLE_PROTOBUF - // Set deactivated, but don't delete any data. - // The Tracer can be activated later - d_activated = false; -#endif - } - /** * @brief Add an attribute to the Trace * - * This only works when Tracer is active - * * @param key * @param value * @return true on success, false when attribute was not added @@ -227,10 +198,10 @@ public: } #endif }; - Closer(const Closer&) = default; + Closer(const Closer&) = delete; Closer& operator=(const Closer&) = default; Closer& operator=(Closer&&) noexcept = default; - Closer(Closer&&) = default; + Closer(Closer&&) = delete; /** * @brief Get the SpanID @@ -297,47 +268,38 @@ private: #ifndef DISABLE_PROTOBUF /** - * @class preActivationSpanInfo - * @brief Used before the Tracer is activated to store Span information + * @class miniSpan + * @brief Used to store Span information */ - struct preActivationSpanInfo + struct miniSpan { std::string name; SpanID span_id; SpanID parent_span_id; uint64_t start_time_unix_nano; uint64_t end_time_unix_nano; + std::vector attributes; }; /** - * @brief Stores all preActivationSpanInfos. It is used until d_activated is true - */ - LockGuarded> d_preActivationSpans; - /** - * @brief Stores all Spans. It is used when d_activated is true + * @brief Stores all miniSpans. */ - LockGuarded> d_postActivationSpans; + LockGuarded> d_spans; /** * @brief All attributes related to this Trace (added to the ScopeSpan) */ std::vector d_attributes; - /** - * @brief All attributes related to the root span of this trace - */ - std::vector d_rootSpanAttributes; /** * @brief The TraceID for this Tracer. It is stable for the lifetime of the Tracer + * + * it is mutable because it is set the first time it is accessed */ - TraceID d_traceid{}; + mutable TraceID d_traceid{}; /** * @brief The last SpanID that was added to this Tracer */ SpanID d_lastSpanID{}; - /** - * @brief Whether or not we are storing full Spans or minimal Spans - */ - bool d_activated{false}; #endif }; } // namespace pdns::trace::dnsdist diff --git a/pdns/dnsdistdist/test-dnsdist-opentelemetry_cc.cc b/pdns/dnsdistdist/test-dnsdist-opentelemetry_cc.cc index 5e544a4bbb..5449f61f22 100644 --- a/pdns/dnsdistdist/test-dnsdist-opentelemetry_cc.cc +++ b/pdns/dnsdistdist/test-dnsdist-opentelemetry_cc.cc @@ -19,6 +19,8 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#include "protozero-trace.hh" +#include #ifndef DISABLE_PROTOBUF #ifndef BOOST_TEST_DYN_LINK #define BOOST_TEST_DYN_LINK @@ -34,24 +36,17 @@ #define BOOST_TEST_NO_MAIN BOOST_AUTO_TEST_SUITE(dnsdistopentelemetry_cc) -BOOST_AUTO_TEST_CASE(getTraceID) +BOOST_AUTO_TEST_CASE(TraceID) { - // Ensure we always have a TraceID after activation + // Ensure we always have a TraceID auto tracer = pdns::trace::dnsdist::Tracer::getTracer(); - BOOST_CHECK_EQUAL(tracer->getTraceID(), TraceID{}); + BOOST_CHECK_NE(tracer->getTraceID(), pdns::trace::s_emptyTraceID); - // Ensure we have one *after* activation - tracer->activate(); - auto traceid = tracer->getTraceID(); - BOOST_CHECK_NE(traceid, TraceID{}); - - // Ensure we have the same one *after* deactivation - tracer->deactivate(); - BOOST_CHECK_EQUAL(tracer->getTraceID(), traceid); - - // Ensure we have the same one *after* reactivation - tracer->deactivate(); - BOOST_CHECK_EQUAL(tracer->getTraceID(), traceid); + // Ensure we have a trace ID, even if we don't call getTraceID + tracer = pdns::trace::dnsdist::Tracer::getTracer(); + tracer->openSpan("bla"); + auto data = tracer->getTracesData(); + BOOST_CHECK_NE(data.resource_spans.at(0).scope_spans.at(0).spans.at(0).trace_id, pdns::trace::s_emptyTraceID); } BOOST_AUTO_TEST_CASE(getLastSpanID) @@ -72,17 +67,6 @@ BOOST_AUTO_TEST_CASE(getLastSpanID) } lastSpanID = tracer->getLastSpanID(); BOOST_CHECK_EQUAL(spanid, lastSpanID); - - tracer->activate(); - spanid = tracer->openSpan("post-activation-myevent").getSpanID(); - lastSpanID = tracer->getLastSpanID(); - BOOST_CHECK_EQUAL(spanid, lastSpanID); - - for (auto i = 0; i < 4; i++) { - spanid = tracer->openSpan("post-activation-myevent" + std::to_string(i)).getSpanID(); - } - lastSpanID = tracer->getLastSpanID(); - BOOST_CHECK_EQUAL(spanid, lastSpanID); } BOOST_AUTO_TEST_CASE(getLastSpanIDForName) @@ -105,65 +89,19 @@ BOOST_AUTO_TEST_CASE(getLastSpanIDForName) } lastSpanID = tracer->getLastSpanIDForName(eventName); BOOST_CHECK_EQUAL(spanid, lastSpanID); - auto preactivationSpanID = spanid; - - tracer->activate(); - spanid = tracer->openSpan(eventName).getSpanID(); - lastSpanID = tracer->getLastSpanIDForName(eventName); - BOOST_CHECK_EQUAL(spanid, lastSpanID); - - for (auto i = 0; i < 4; i++) { - spanid = tracer->openSpan(eventName).getSpanID(); - } - lastSpanID = tracer->getLastSpanIDForName(eventName); - BOOST_CHECK_EQUAL(spanid, lastSpanID); - - tracer->deactivate(); - lastSpanID = tracer->getLastSpanIDForName(eventName); - BOOST_CHECK_EQUAL(preactivationSpanID, lastSpanID); -} - -BOOST_AUTO_TEST_CASE(activate) -{ - auto tracer = pdns::trace::dnsdist::Tracer::getTracer(); - - // We don't actually check the internal state, but we infer it from the order - // of the output. - auto preActivationSpanID = tracer->openSpan("pre-activation-event").getSpanID(); - tracer->activate(); - auto postActivationSpanID = tracer->openSpan("post-activation-event").getSpanID(); - - // Ensure order is pre1, post1 - auto trace = tracer->getTracesData(); - BOOST_ASSERT(trace.resource_spans.at(0).scope_spans.at(0).spans.size() == 2); - BOOST_CHECK_EQUAL(trace.resource_spans.at(0).scope_spans.at(0).spans.at(0).span_id, preActivationSpanID); - BOOST_CHECK_EQUAL(trace.resource_spans.at(0).scope_spans.at(0).spans.at(1).span_id, postActivationSpanID); - - // Now deactivate and check if the order will be pre1, pre2, post1 - tracer->deactivate(); - auto preActivationSpanID2 = tracer->openSpan("pre-activation-event2").getSpanID(); - - trace = tracer->getTracesData(); - BOOST_ASSERT(trace.resource_spans.at(0).scope_spans.at(0).spans.size() == 3); - BOOST_CHECK_EQUAL(trace.resource_spans.at(0).scope_spans.at(0).spans.at(0).span_id, preActivationSpanID); - BOOST_CHECK_EQUAL(trace.resource_spans.at(0).scope_spans.at(0).spans.at(1).span_id, preActivationSpanID2); - BOOST_CHECK_EQUAL(trace.resource_spans.at(0).scope_spans.at(0).spans.at(2).span_id, postActivationSpanID); } BOOST_AUTO_TEST_CASE(Closer) { auto tracer = pdns::trace::dnsdist::Tracer::getTracer(); - auto prespanid = tracer->openSpan("foo").getSpanID(); - tracer->activate(); - auto postspanid = tracer->openSpan("bar").getSpanID(); + auto spanid = tracer->openSpan("foo").getSpanID(); SpanID openeventSpanID; SpanID openevent2SpanID; { - auto precloser = tracer->getCloser(prespanid); - auto postcloser = tracer->getCloser(postspanid); + auto closer = tracer->getCloser(spanid); auto openEventCloser = tracer->openSpan("openEvent"); openeventSpanID = openEventCloser.getSpanID(); @@ -176,65 +114,69 @@ BOOST_AUTO_TEST_CASE(Closer) // Closer is out of scope, so each event should have a closing time auto trace = tracer->getTracesData(); - BOOST_ASSERT(trace.resource_spans.at(0).scope_spans.at(0).spans.size() == 4); + BOOST_ASSERT(trace.resource_spans.at(0).scope_spans.at(0).spans.size() == 3); - BOOST_CHECK_EQUAL(trace.resource_spans.at(0).scope_spans.at(0).spans.at(0).span_id, prespanid); + BOOST_CHECK_EQUAL(trace.resource_spans.at(0).scope_spans.at(0).spans.at(0).span_id, spanid); BOOST_CHECK_NE(trace.resource_spans.at(0).scope_spans.at(0).spans.at(0).end_time_unix_nano, 0U); - BOOST_CHECK_EQUAL(trace.resource_spans.at(0).scope_spans.at(0).spans.at(1).span_id, postspanid); BOOST_CHECK_NE(trace.resource_spans.at(0).scope_spans.at(0).spans.at(1).end_time_unix_nano, 0U); - - BOOST_CHECK_NE(trace.resource_spans.at(0).scope_spans.at(0).spans.at(2).end_time_unix_nano, 0U); - BOOST_CHECK_NE(trace.resource_spans.at(0).scope_spans.at(0).spans.at(3).end_time_unix_nano, 0U); + BOOST_CHECK_NE(trace.resource_spans.at(0).scope_spans.at(0).spans.at(1).end_time_unix_nano, 0U); // Check the parent span_id for the second closer - BOOST_CHECK_EQUAL(trace.resource_spans.at(0).scope_spans.at(0).spans.at(3).span_id, openevent2SpanID); - BOOST_CHECK_EQUAL(trace.resource_spans.at(0).scope_spans.at(0).spans.at(3).parent_span_id, openeventSpanID); + BOOST_CHECK_EQUAL(trace.resource_spans.at(0).scope_spans.at(0).spans.at(2).span_id, openevent2SpanID); + BOOST_CHECK_EQUAL(trace.resource_spans.at(0).scope_spans.at(0).spans.at(2).parent_span_id, openeventSpanID); pdns::trace::dnsdist::Tracer::Closer emptyCloser; BOOST_CHECK_EQUAL(emptyCloser.getSpanID(), SpanID{}); } -BOOST_AUTO_TEST_CASE(attributes) +BOOST_AUTO_TEST_CASE(traceAttributes) { auto tracer = pdns::trace::dnsdist::Tracer::getTracer(); tracer->setTraceAttribute("foo", AnyValue{"bar"}); - // Test that no attributes are added when the tracer is not activated auto trace = tracer->getTracesData(); BOOST_CHECK_EQUAL(trace.resource_spans.at(0).resource.attributes.size(), 1U); BOOST_CHECK_EQUAL(trace.resource_spans.at(0).resource.attributes.at(0).key, "service.name"); // Check if we have a hostname - BOOST_CHECK_EQUAL(trace.resource_spans.at(0).scope_spans.at(0).scope.attributes.size(), 1U); - BOOST_CHECK_EQUAL(trace.resource_spans.at(0).scope_spans.at(0).scope.attributes.at(0).key, "hostname"); + BOOST_CHECK_EQUAL(trace.resource_spans.at(0).scope_spans.at(0).scope.attributes.size(), 2U); - // Now activate and add 2 attributes - tracer->activate(); - tracer->setTraceAttribute("foo", AnyValue{"bar"}); - tracer->setTraceAttribute("baz", AnyValue{256}); + BOOST_CHECK_EQUAL(trace.resource_spans.at(0).scope_spans.at(0).scope.attributes.at(0).key, "foo"); + BOOST_CHECK_EQUAL(trace.resource_spans.at(0).scope_spans.at(0).scope.attributes.at(0).value, AnyValue{"bar"}); - trace = tracer->getTracesData(); + BOOST_CHECK_EQUAL(trace.resource_spans.at(0).scope_spans.at(0).scope.attributes.at(1).key, "hostname"); +} - BOOST_ASSERT(trace.resource_spans.at(0).resource.attributes.size() == 1); - // hostname plus the two we set - BOOST_ASSERT(trace.resource_spans.at(0).scope_spans.at(0).scope.attributes.size() == 3); +BOOST_AUTO_TEST_CASE(spanAttributes) +{ + auto tracer = pdns::trace::dnsdist::Tracer::getTracer(); + auto closer = tracer->openSpan("myspan"); + auto spanid = closer.getSpanID(); + tracer->setSpanAttribute(spanid, "foo", AnyValue{42}); + auto trace = tracer->getTracesData(); - BOOST_CHECK_EQUAL(trace.resource_spans.at(0).scope_spans.at(0).scope.attributes.at(0).key, "foo"); - BOOST_CHECK_EQUAL(trace.resource_spans.at(0).scope_spans.at(0).scope.attributes.at(0).value, AnyValue{"bar"}); + BOOST_CHECK_EQUAL(trace.resource_spans.at(0).scope_spans.at(0).spans.size(), 1U); + BOOST_CHECK_EQUAL(trace.resource_spans.at(0).scope_spans.at(0).spans.at(0).attributes.size(), 1U); + BOOST_CHECK_EQUAL(trace.resource_spans.at(0).scope_spans.at(0).spans.at(0).attributes.at(0).key, "foo"); + BOOST_CHECK_EQUAL(trace.resource_spans.at(0).scope_spans.at(0).spans.at(0).attributes.at(0).value, AnyValue{42}); +} - BOOST_CHECK_EQUAL(trace.resource_spans.at(0).scope_spans.at(0).scope.attributes.at(1).key, "baz"); - BOOST_CHECK_EQUAL(trace.resource_spans.at(0).scope_spans.at(0).scope.attributes.at(1).value, AnyValue{256}); +BOOST_AUTO_TEST_CASE(rootSpanAttributes) +{ + auto tracer = pdns::trace::dnsdist::Tracer::getTracer(); + auto closer = tracer->openSpan("myspan"); + auto spanid = closer.getSpanID(); + tracer->openSpan("not root", spanid); - // Add a span and some attributes - auto spanid = tracer->openSpan("anEvent").getSpanID(); - tracer->setSpanAttribute(spanid, "spanattr", AnyValue{"exciting"}); + tracer->setRootSpanAttribute("foobar", AnyValue{"baz"}); - trace = tracer->getTracesData(); + auto trace = tracer->getTracesData(); - BOOST_ASSERT(trace.resource_spans.at(0).scope_spans.at(0).spans.at(0).attributes.size() == 1); - BOOST_CHECK_EQUAL(trace.resource_spans.at(0).scope_spans.at(0).spans.at(0).attributes.front().key, "spanattr"); - BOOST_CHECK_EQUAL(trace.resource_spans.at(0).scope_spans.at(0).spans.at(0).attributes.front().value, AnyValue{"exciting"}); + BOOST_CHECK_EQUAL(trace.resource_spans.at(0).scope_spans.at(0).spans.size(), 2U); + BOOST_CHECK_EQUAL(trace.resource_spans.at(0).scope_spans.at(0).spans.at(0).attributes.size(), 1U); + BOOST_CHECK_EQUAL(trace.resource_spans.at(0).scope_spans.at(0).spans.at(0).attributes.at(0).key, "foobar"); + BOOST_CHECK_EQUAL(trace.resource_spans.at(0).scope_spans.at(0).spans.at(0).attributes.at(0).value, AnyValue{"baz"}); } BOOST_AUTO_TEST_CASE(getOTProtobuf) @@ -243,7 +185,6 @@ BOOST_AUTO_TEST_CASE(getOTProtobuf) auto data = tracer->getOTProtobuf(); BOOST_TEST(data.size() >= 100U); - tracer->activate(); tracer->setTraceAttribute("foo", AnyValue{"bar"}); data = tracer->getOTProtobuf(); BOOST_TEST(data.size() >= 110U);