otTrace.resource_spans.at(0).scope_spans.at(0).scope.attributes.push_back(hostnameAttr);
auto traceid = getTraceID();
+
for (auto const& lockedSpan : *d_spans.read_only_lock()) {
otTrace.resource_spans.at(0).scope_spans.at(0).spans.push_back(
{
.trace_id = traceid,
- .span_id = lockedSpan.span_id,
- .parent_span_id = lockedSpan.parent_span_id,
+ .span_id = lockedSpan.span_id == d_oldAndNewRootSpanID.oldID ? d_oldAndNewRootSpanID.newID : lockedSpan.span_id,
+ .parent_span_id = lockedSpan.parent_span_id == d_oldAndNewRootSpanID.oldID ? d_oldAndNewRootSpanID.newID : lockedSpan.parent_span_id,
.name = lockedSpan.name,
.kind = pdns::trace::Span::SpanKind::SPAN_KIND_SERVER,
.start_time_unix_nano = lockedSpan.start_time_unix_nano,
#ifdef DISABLE_PROTOBUF
return 0;
#else
- return addSpan(name, SpanID{});
+ return addSpan(name, getLastSpanID());
#endif
}
.attributes = {},
});
- d_lastSpanID = spanID;
+ d_spanIDStack.push_back(spanID);
return spanID;
#endif
}
void Tracer::setRootSpanID([[maybe_unused]] const SpanID& spanID)
{
#ifndef DISABLE_PROTOBUF
- // XXX: We just assume that the first Span is the RootSpan
SpanID oldRootSpanID;
- if (auto lockedSpans = d_spans.lock(); !lockedSpans->empty()) {
- oldRootSpanID = lockedSpans->begin()->span_id;
- lockedSpans->begin()->span_id = spanID;
- for (auto& span : *lockedSpans) {
- if (span.parent_span_id == oldRootSpanID) {
- span.parent_span_id = spanID;
- }
+ 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()) {
+ oldRootSpanID = iter->span_id;
}
}
+ if (oldRootSpanID == pdns::trace::s_emptySpanID) {
+ return;
+ }
+ d_oldAndNewRootSpanID.oldID = oldRootSpanID;
+ d_oldAndNewRootSpanID.newID = spanID;
#endif
}
[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;
+
+ // Only closers are allowed, so this can never happen
+ assert(!d_spanIDStack.empty());
+ assert(d_spanIDStack.back() == spanID);
+ d_spanIDStack.pop_back();
}
#endif
}
#ifdef DISABLE_PROTOBUF
return 0;
#else
+ if (d_oldAndNewRootSpanID.newID != pdns::trace::s_emptySpanID) {
+ return d_oldAndNewRootSpanID.newID;
+ }
+
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;
}
}
- return SpanID{};
+ return pdns::trace::s_emptySpanID;
#endif
}
#ifdef DISABLE_PROTOBUF
return 0;
#else
- if (auto lockedSpans = d_spans.read_only_lock(); !lockedSpans->empty()) {
- return lockedSpans->back().span_id;
+ if (d_spanIDStack.empty()) {
+ return pdns::trace::s_emptySpanID;
}
- return pdns::trace::s_emptySpanID;
+ if (d_spanIDStack.size() == 1 && d_spanIDStack.front() == d_oldAndNewRootSpanID.oldID) {
+ return d_oldAndNewRootSpanID.newID;
+ }
+ return d_spanIDStack.back();
#endif
}
* @brief Stores all miniSpans.
*/
LockGuarded<std::vector<miniSpan>> d_spans;
+
/**
* @brief All attributes related to this Trace (added to the ScopeSpan)
*/
* it is mutable because it is set the first time it is accessed
*/
mutable LockGuarded<TraceID> d_traceid{};
+
+ /**
+ * @brief A stack of SpanID's that tracks the "stack" of SpanIDs
+ */
+ std::vector<SpanID> d_spanIDStack;
+
/**
- * @brief The last SpanID that was added to this Tracer
+ * Set when setRootSpanID is called, used to replace the
+ * root span id (and the parent span ids) when the PB is generated
*/
- SpanID d_lastSpanID{};
+ struct
+ {
+ SpanID oldID;
+ SpanID newID;
+ } d_oldAndNewRootSpanID;
#endif
};
} // namespace pdns::trace::dnsdist
BOOST_CHECK_EQUAL(lastSpanID, SpanID{});
// Add event before activation
- auto spanid = tracer->openSpan("myevent").getSpanID();
+ auto closer = tracer->openSpan("myevent");
+ auto spanid = closer.getSpanID();
lastSpanID = tracer->getLastSpanID();
BOOST_CHECK_EQUAL(spanid, lastSpanID);
for (auto i = 0; i < 4; i++) {
- spanid = tracer->openSpan("myevent" + std::to_string(i)).getSpanID();
+ auto closer2 = tracer->openSpan("myevent" + std::to_string(i));
+ spanid = closer2.getSpanID();
+ lastSpanID = tracer->getLastSpanID();
}
- lastSpanID = tracer->getLastSpanID();
BOOST_CHECK_EQUAL(spanid, lastSpanID);
}
SpanID openevent2SpanID;
{
- auto closer = tracer->getCloser(spanid);
-
auto openEventCloser = tracer->openSpan("openEvent");
openeventSpanID = openEventCloser.getSpanID();
auto openEventCloser2 = tracer->openSpan("openEvent2", openeventSpanID);