dnsdist-metrics.cc dnsdist-metrics.hh \
dnsdist-nghttp2-in.hh \
dnsdist-nghttp2.hh \
+ dnsdist-opentelemetry.cc dnsdist-opentelemetry.hh \
dnsdist-prometheus.hh \
dnsdist-protobuf.cc dnsdist-protobuf.hh \
dnsdist-protocols.cc dnsdist-protocols.hh \
packetcache.hh \
pdnsexception.hh \
pollmplexer.cc \
+ protozero-trace.cc protozero-trace.hh \
protozero.cc protozero.hh \
proxy-protocol.cc proxy-protocol.hh \
qtype.cc qtype.hh \
- name: "ttl"
type: "u32"
description: "The TTL to use"
+- name: "SetTrace"
+ description: "Enable or disable OpenTelemetry tracing for this query. Don't forget to also use a RemoteLog action to actually send the trace. Subsequent rules are processed after this action"
+ parameters:
+ - name: "value"
+ type: "bool"
+ description: "Whether or not to enable tracing"
- name: "SNMPTrap"
description: "Send an SNMP trap, adding the message string as the query description. Subsequent rules are processed after this action"
parameters:
#include "ipcipher.hh"
#include "dnsdist-ipcrypt2.hh"
#include "iputils.hh"
+#include "protozero-trace.hh"
+#include "qtype.hh"
#include "remote_logger.hh"
#include "svc-records.hh"
#include "threadname.hh"
std::string d_ipEncryptMethod;
std::optional<pdns::ipcrypt2::IPCrypt2> d_ipcrypt2{std::nullopt};
};
-
#endif /* DISABLE_PROTOBUF */
+class SetTraceAction : public DNSAction
+{
+public:
+ SetTraceAction(bool value) :
+ d_value{value} {};
+
+ DNSAction::Action operator()([[maybe_unused]] DNSQuestion* dnsquestion, std::string* ruleresult) const override
+ {
+ (void)ruleresult;
+#ifndef DISABLE_PROTOBUF
+ if (d_value) {
+ dnsquestion->ids.d_OTTracer->activate();
+ dnsquestion->ids.d_OTTracer->setTraceAttribute("query.qname", AnyValue{dnsquestion->ids.qname.toStringNoDot()});
+ dnsquestion->ids.d_OTTracer->setTraceAttribute("query.qtype", AnyValue{QType(dnsquestion->ids.qtype).toString()});
+ dnsquestion->ids.d_OTTracer->setTraceAttribute("query.remote", AnyValue{dnsquestion->ids.origRemote.toLogString()});
+ }
+ else {
+ dnsquestion->ids.d_OTTracer->deactivate();
+ }
+ dnsquestion->ids.tracingEnabled = d_value;
+#endif
+ return Action::None;
+ }
+
+ [[nodiscard]] std::string toString() const override
+ {
+ return string((d_value ? "en" : "dis")) + string("able OpenTelemetry Tracing");
+ }
+
+private:
+ bool d_value;
+};
+
class SNMPTrapAction : public DNSAction
{
public:
*/
#pragma once
+#include <cstdint>
+#include <ctime>
+#include <optional>
#include <unordered_map>
+#include <utility>
+#include <vector>
#include "config.h"
#include "dnscrypt.hh"
#include "gettime.hh"
#include "iputils.hh"
#include "noinitvector.hh"
+#include "dnsdist-opentelemetry.hh"
#include "uuid-utils.hh"
struct ClientState;
std::string d_requestorID;
};
+ // Whether or not Open Telemetry tracing is enabled for this query
+ bool tracingEnabled = false;
+
+ // TODO: Do we want to keep some data *without* creating a tracer for each query?
+ // TODO: shard_ptr to work with Tracer::Closer?
+ std::unique_ptr<pdns::trace::dnsdist::Tracer> d_OTTracer{new pdns::trace::dnsdist::Tracer};
+
InternalQueryState()
{
origDest.sin4.sin_family = 0;
--- /dev/null
+/*
+ * This file is part of PowerDNS or dnsdist.
+ * Copyright -- PowerDNS.COM B.V. and its contributors
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * In addition, for the avoidance of any doubt, permission is granted to
+ * link this program with OpenSSL and to (re)distribute the binaries
+ * produced as the result of such linking.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "dnsdist-opentelemetry.hh"
+
+#include <vector>
+
+#ifndef DISABLE_PROTOBUF
+#include "protozero-trace.hh"
+#endif
+
+namespace pdns::trace::dnsdist
+{
+
+TracesData Tracer::getTracesData() const
+{
+#ifdef DISABLE_PROTOBUF
+ return 0;
+#else
+ auto otTrace = pdns::trace::TracesData{
+ .resource_spans = {
+ pdns::trace::ResourceSpans{
+ .resource = {
+ .attributes = std::vector<pdns::trace::KeyValue>{
+ pdns::trace::KeyValue{
+ "service.name", pdns::trace::AnyValue{"dnsdist"}},
+ }},
+ .scope_spans = std::vector<pdns::trace::ScopeSpans>{{}}}}};
+
+ otTrace.resource_spans.at(0).resource.attributes.insert(
+ otTrace.resource_spans.at(0).resource.attributes.end(),
+ d_attributes.begin(),
+ d_attributes.end());
+
+ for (auto const& preActivationTrace : d_preActivationSpans) {
+ 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,
+ .start_time_unix_nano = preActivationTrace.start_time_unix_nano,
+ .end_time_unix_nano = preActivationTrace.end_time_unix_nano,
+ });
+ }
+
+ otTrace.resource_spans.at(0).scope_spans.at(0).spans.insert(
+ otTrace.resource_spans.at(0).scope_spans.at(0).spans.end(),
+ d_postActivationSpans.begin(),
+ d_postActivationSpans.end());
+ return otTrace;
+#endif
+}
+
+std::string Tracer::getOTProtobuf() const
+{
+#ifdef DISABLE_PROTOBUF
+ return 0;
+#else
+ // TODO: Should we close all spans?
+ return getTracesData().encode();
+#endif
+}
+
+SpanID Tracer::addSpan([[maybe_unused]] const std::string& name)
+{
+#ifdef DISABLE_PROTOBUF
+ return 0;
+#else
+ return addSpan(name, SpanID{});
+#endif
+}
+
+SpanID Tracer::addSpan([[maybe_unused]] const std::string& name, [[maybe_unused]] const SpanID& parentSpanID)
+{
+#ifdef DISABLE_PROTOBUF
+ return 0;
+#else
+ auto spanID = pdns::trace::randomSpanID();
+ if (d_activated) {
+ d_postActivationSpans.push_back({
+ .trace_id = d_traceid,
+ .span_id = spanID,
+ .parent_span_id = parentSpanID,
+ .name = name,
+ .start_time_unix_nano = pdns::trace::timestamp(),
+ });
+ return spanID;
+ }
+
+ // We're not activated, so we are in pre-activation.
+ d_preActivationSpans.push_back({
+ .name = name,
+ .span_id = spanID,
+ .parent_span_id = parentSpanID,
+ .start_time_unix_nano = pdns::trace::timestamp(),
+ .end_time_unix_nano = 0,
+ });
+
+ d_lastSpanID = spanID;
+
+ return spanID;
+#endif
+}
+
+// TODO: Figure out what to do with duplicate keys
+bool Tracer::setTraceAttribute([[maybe_unused]] const std::string& key, [[maybe_unused]] const AnyValue& value)
+{
+#ifdef DISABLE_PROTOBUF
+ // always succesfull
+ return true;
+#else
+ if (!d_activated) {
+ return false;
+ }
+ d_attributes.push_back({key, value});
+ return true;
+#endif
+}
+
+void Tracer::closeSpan([[maybe_unused]] const SpanID& spanID)
+{
+#ifndef DISABLE_PROTOBUF
+ if (d_activated) {
+ auto spanIt = std::find_if(
+ d_postActivationSpans.rbegin(),
+ d_postActivationSpans.rend(),
+ [spanID](const pdns::trace::Span& span) { return span.span_id == spanID; });
+ if (spanIt != d_postActivationSpans.rend()) {
+ if (spanIt->end_time_unix_nano == 0) {
+ spanIt->end_time_unix_nano = pdns::trace::timestamp();
+ }
+ return;
+ }
+ }
+
+ auto spanIt = std::find_if(
+ d_preActivationSpans.rbegin(),
+ d_preActivationSpans.rend(),
+ [spanID](const preActivationSpanInfo& span) { return span.span_id == spanID; });
+ if (spanIt != d_preActivationSpans.rend() && spanIt->end_time_unix_nano == 0) {
+ spanIt->end_time_unix_nano = pdns::trace::timestamp();
+ return;
+ }
+#endif
+}
+
+// TODO: Figure out what to do with duplicate keys
+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) {
+ if (auto iter = std::find_if(d_postActivationSpans.rbegin(),
+ d_postActivationSpans.rend(),
+ [spanid](const pdns::trace::Span& span) { return span.span_id == spanid; });
+ iter != d_postActivationSpans.rend()) {
+ iter->attributes.push_back({key, value});
+ return;
+ }
+ }
+ // XXX: It is not possible to add attributes to d_preActivationTraces. Perhaps these should be converted on calling activate
+#endif
+}
+
+SpanID Tracer::getLastSpanID() const
+{
+#ifdef DISABLE_PROTOBUF
+ return 0;
+#else
+ if (d_activated && d_postActivationSpans.size() != 0) {
+ return d_postActivationSpans.back().span_id;
+ }
+ if (d_preActivationSpans.size() != 0) {
+ return d_preActivationSpans.back().span_id;
+ }
+ return SpanID{};
+#endif
+}
+
+SpanID Tracer::getLastSpanIDForName([[maybe_unused]] const std::string& name) const
+{
+#ifdef DISABLE_PROTOBUF
+ return 0;
+#else
+ if (d_activated && d_postActivationSpans.size() != 0) {
+ if (auto iter = std::find_if(d_postActivationSpans.rbegin(),
+ d_postActivationSpans.rend(),
+ [name](const pdns::trace::Span& span) { return span.name == name; });
+ iter != d_postActivationSpans.rend()) {
+ return iter->span_id;
+ }
+ }
+
+ if (d_preActivationSpans.size() != 0) {
+ if (auto iter = std::find_if(d_preActivationSpans.rbegin(),
+ d_preActivationSpans.rend(),
+ [name](const preActivationSpanInfo& span) { return span.name == name; });
+ iter != d_preActivationSpans.rend()) {
+ return iter->span_id;
+ }
+ }
+ return SpanID{};
+#endif
+}
+
+TraceID Tracer::getTraceID() const
+{
+#ifdef DISABLE_PROTOBUF
+ return 0;
+#else
+ return d_traceid;
+#endif
+}
+
+Tracer::Closer Tracer::getCloser([[maybe_unused]] const SpanID& spanid)
+{
+#ifdef DISABLE_PROTOBUF
+ return Tracer::Closer();
+#else
+ return {this, spanid};
+#endif
+}
+
+Tracer::Closer Tracer::openSpan([[maybe_unused]] const std::string& name)
+{
+#ifdef DISABLE_PROTOBUF
+ return Tracer::Closer();
+#else
+ auto spanid = addSpan(name);
+ return getCloser(spanid);
+#endif
+}
+
+Tracer::Closer Tracer::openSpan([[maybe_unused]] const std::string& name, [[maybe_unused]] const SpanID& parentSpanID)
+{
+#ifdef DISABLE_PROTOBUF
+ return Tracer::Closer();
+#else
+ auto spanid = addSpan(name, parentSpanID);
+ return getCloser(spanid);
+#endif
+}
+
+SpanID Tracer::Closer::getSpanID() const
+{
+#ifdef DISABLE_PROTOBUF
+ return 0;
+#else
+ return d_spanID;
+#endif
+}
+
+} // namespace pdns::trace::dnsdist
--- /dev/null
+/*
+ * This file is part of PowerDNS or dnsdist.
+ * Copyright -- PowerDNS.COM B.V. and its contributors
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * In addition, for the avoidance of any doubt, permission is granted to
+ * link this program with OpenSSL and to (re)distribute the binaries
+ * produced as the result of such linking.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#pragma once
+
+#include <string>
+#include <vector>
+
+#ifndef DISABLE_PROTOBUF
+#include "protozero-trace.hh"
+using TraceID = pdns::trace::TraceID;
+using SpanID = pdns::trace::SpanID;
+using AnyValue = pdns::trace::AnyValue;
+using TracesData = pdns::trace::TracesData;
+#else
+// Define the minimal things needed
+#include <variant>
+using TraceID = int;
+using SpanID = int;
+using AnyValue = std::variant<std::string, int>;
+using TracesData = int;
+#endif
+
+/*
+ * This namespace contains all the bits and pieces required to do OpenTelemetry
+ * traces in dnsdist. It is contained in this header and cc-file to ensure the rest
+ * of the code is not littered with #ifdefs for DISABLE_PROTOBUF. All functions and
+ * other public members can be safely called/manipulated in a non-protobuf build of
+ * dnsdist.
+ *
+ * The idea is inspired by the rec-eventtrace.{cc,hh} files.
+ *
+ * Although the namespace contains dnsdist, it might be general enough to be
+ * reused (after renaming the namespace) by auth and recursor
+ */
+namespace pdns::trace::dnsdist
+{
+
+/**
+ * @class Tracer
+ * @brief This class holds a single trace instance
+ *
+ */
+class Tracer
+{
+public:
+ Tracer() = default;
+ ~Tracer() = default;
+ Tracer(const Tracer&) = delete;
+ Tracer& operator=(const Tracer) = delete;
+ Tracer& operator=(Tracer&&) = delete;
+ Tracer(Tracer&&) = delete;
+
+ /**
+ * @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) {
+ pdns::trace::random(d_traceid);
+ }
+#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
+ */
+ bool setTraceAttribute(const std::string& key, const AnyValue& value);
+
+ /**
+ * @brief Set an attribute on a Span
+ *
+ * This does not work when the Tracer is not active
+ *
+ * @param spanID The SpanID of the Span to add the attribute to
+ * @param key
+ * @param value
+ */
+ void setSpanAttribute(const SpanID& spanID, const std::string& key, const AnyValue& value);
+
+ /**
+ * @brief Sets the stop timestamp for a span
+ *
+ * When a Span is already closed, the timestamp is not updated
+ *
+ * @param spanID The ID of the Span to set the end time for
+ */
+ void closeSpan(const SpanID& spanID);
+
+ /**
+ * @brief Get the last SpanID generated
+ *
+ * @return The last generated SpanID, or empty SpanID when none exist
+ */
+ [[nodiscard]] SpanID getLastSpanID() const;
+
+ /**
+ * @brief Get the SpanID for the most recently added span with a name
+ *
+ * @param name The name of the Span
+ * @return The SpanID, or empty SpanID when none are found
+ */
+ [[nodiscard]] SpanID getLastSpanIDForName(const std::string& name) const;
+
+ /**
+ * @brief Retrieve the TraceID for this Tracer
+ */
+ [[nodiscard]] TraceID getTraceID() const;
+
+ /**
+ * @brief Generate the TracesData from all data in this Tracer
+ *
+ * @return pdns::trace::TracesData
+ */
+ [[nodiscard]] TracesData getTracesData() const;
+
+ /**
+ * @brief Get the TracesData as protobuf encoded OpenTelemetry data
+ */
+ [[nodiscard]] std::string getOTProtobuf() const;
+
+ /**
+ * @class Closer
+ * @brief Automatically closes a Span when it goes out of scope
+ *
+ * This is a helper that _somewhat_ implements Go's `defer` in C++ semantics
+ * Basically, it stores a pointer to the Tracer and a SpanID.
+ * When the object goes out of scope, the closeSpan function is called
+ */
+ class Closer
+ {
+ public:
+ /**
+ * @brief An empty Closer, not really useful
+ */
+#ifdef DISABLE_PROTOBUF
+ Closer() = default;
+#else
+ Closer() :
+ d_tracer(nullptr), d_spanID(SpanID{}) {};
+ /**
+ * @brief Create a Closer
+ *
+ * There should be no need to call this directly. Use one of these functions to get one:
+ *
+ * Tracer::getCloser
+ * Tracer::openSpan
+ *
+ * @param tracer A pointer to the Tracer where we want to close a Span
+ * @param spanid The SpanID to close in the Tracer
+ */
+ Closer(Tracer* tracer, const SpanID& spanid) :
+ d_tracer(tracer), d_spanID(spanid) {};
+#endif
+
+ /**
+ * @brief Closes the Span in the Tracer
+ */
+ ~Closer()
+ {
+#ifndef DISABLE_PROTOBUF
+ if (d_tracer != nullptr) {
+ d_tracer->closeSpan(d_spanID);
+ }
+#endif
+ };
+ Closer(const Closer&) = default;
+ Closer& operator=(const Closer&) = default;
+ Closer& operator=(Closer&&) noexcept = default;
+ Closer(Closer&&) = default;
+
+ /**
+ * @brief Get the SpanID
+ *
+ * @return
+ */
+ [[nodiscard]] SpanID getSpanID() const;
+
+ private:
+#ifndef DISABLE_PROTOBUF
+ // XXX: Should we make this a shared_ptr and force all consumers to Tracer to keep it as a shared_ptr as well?
+ Tracer* d_tracer;
+ SpanID d_spanID;
+#endif
+ };
+
+ /**
+ * @brief Get a Closer for spanid in this Tracer
+ *
+ * @param spanid The SpanID that will close when the Closer is destructed
+ * @return Tracer::Closer
+ */
+ Closer getCloser(const SpanID& spanid);
+
+ /**
+ * @brief Add a new Span
+ *
+ * @param name The name for this span
+ * @return Tracer::Closer for the newly created Span
+ */
+ Closer openSpan(const std::string& name);
+
+ /**
+ * @brief Add a new Span which is a child of another Span
+ *
+ * @param name The name for this span
+ * @param parentSpanID The SpanID of the parent Trace
+ * @return Tracer::Closer for the newly created Span
+ */
+ Closer openSpan(const std::string& name, const SpanID& parentSpanID);
+
+private:
+ /**
+ * @brief Create a new Span
+ *
+ * The Span's start time is set to the current time
+ *
+ * @param name The name for this span
+ * @return The SpanID of the created Span
+ */
+ SpanID addSpan(const std::string& name);
+
+ /**
+ * @brief Create a new Span with a parent
+ *
+ * The Span's start time is set to the current time
+ *
+ * @param name The name for this span
+ * @param parentSpanID The SpanID of the parent Span (not verified)
+ * @return The SpanID of the created Span
+ */
+ SpanID addSpan(const std::string& name, const SpanID& parentSpanID);
+
+#ifndef DISABLE_PROTOBUF
+ /**
+ * @class preActivationSpanInfo
+ * @brief Used before the Tracer is activated to store Span information
+ */
+ struct preActivationSpanInfo
+ {
+ std::string name;
+ SpanID span_id;
+ SpanID parent_span_id;
+ uint64_t start_time_unix_nano;
+ uint64_t end_time_unix_nano;
+ };
+
+ /**
+ * @brief Stores all preActivationSpanInfos. It is used until d_activated is true
+ */
+ std::vector<preActivationSpanInfo> d_preActivationSpans;
+ /**
+ * @brief Stores all Spans. It is used when d_activated is true
+ */
+ std::vector<Span> d_postActivationSpans;
+ /**
+ * @brief All attributes related to this Trace
+ */
+ std::vector<pdns::trace::KeyValue> d_attributes;
+
+ /**
+ * @brief The TraceID for this Tracer. It is stable for the lifetime of the Tracer
+ */
+ 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
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "config.h"
+#include "protozero-trace.hh"
+#include <vector>
#ifndef DISABLE_PROTOBUF
#include "base64.hh"
msg.setMeta(key, {std::string()}, {});
}
}
+
+ if (d_dq.ids.tracingEnabled) {
+ msg.setOpenTelemtryTraceID(d_dq.ids.d_OTTracer->getTraceID());
+ msg.setOpenTelemetryData(d_dq.ids.d_OTTracer->getOTProtobuf());
+ }
}
ProtoBufMetaKey::ProtoBufMetaKey(const std::string& key)
#pragma once
#include "dnsname.hh"
+#include <optional>
#ifndef DISABLE_PROTOBUF
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/key_extractors.hpp>
#include "protozero.hh"
+#include "protozero-trace.hh"
struct DNSQuestion;
struct DNSResponse;
pdns::ProtoZero::Message::MessageType d_type{pdns::ProtoZero::Message::MessageType::DNSQueryType};
bool d_includeCNAME{false};
+
+ std::optional<std::vector<pdns::trace::Span>> d_traceSpans{std::nullopt};
};
class ProtoBufMetaKey
#include <grp.h>
#include <limits>
#include <netinet/tcp.h>
+#include <optional>
#include <pwd.h>
#include <set>
#include <sys/resource.h>
#include <unistd.h>
+#include "dns.hh"
+#include "dnsdist-idstate.hh"
+#include "dnsdist-opentelemetry.hh"
#include "dnsdist-systemd.hh"
+#include "protozero-trace.hh"
#ifdef HAVE_SYSTEMD
#include <systemd/sd-daemon.h>
#endif
bool applyRulesToResponse(const std::vector<dnsdist::rules::ResponseRuleAction>& respRuleActions, DNSResponse& dnsResponse)
{
+ pdns::trace::dnsdist::Tracer::Closer closer;
+ if (dnsResponse.ids.tracingEnabled) {
+ closer = dnsResponse.ids.d_OTTracer->openSpan("applyRulesToResponse", dnsResponse.ids.d_OTTracer->getLastSpanID());
+ }
if (respRuleActions.empty()) {
return true;
}
bool processResponseAfterRules(PacketBuffer& response, DNSResponse& dnsResponse, [[maybe_unused]] bool muted)
{
+ pdns::trace::dnsdist::Tracer::Closer closer;
+ if (dnsResponse.ids.tracingEnabled) {
+ closer = dnsResponse.ids.d_OTTracer->openSpan("processResponseAfterRules");
+ }
bool zeroScope = false;
if (!fixUpResponse(response, dnsResponse.ids.qname, dnsResponse.ids.origFlags, dnsResponse.ids.ednsAdded, dnsResponse.ids.ecsAdded, dnsResponse.ids.useZeroScope ? &zeroScope : nullptr)) {
+ if (dnsResponse.ids.tracingEnabled) {
+ dnsResponse.ids.d_OTTracer->setSpanAttribute(closer.getSpanID(), "result", AnyValue{"fixUpResponse->false"});
+ }
return false;
}
// if zeroScope, pass the pre-ECS hash-key and do not pass the subnet to the cache
cacheKey = dnsResponse.ids.cacheKeyNoECS;
}
- dnsResponse.ids.packetCache->insert(cacheKey, zeroScope ? boost::none : dnsResponse.ids.subnet, dnsResponse.ids.cacheFlags, dnsResponse.ids.dnssecOK ? *dnsResponse.ids.dnssecOK : false, dnsResponse.ids.qname, dnsResponse.ids.qtype, dnsResponse.ids.qclass, response, dnsResponse.ids.forwardedOverUDP, dnsResponse.getHeader()->rcode, dnsResponse.ids.tempFailureTTL);
-
+ {
+ pdns::trace::dnsdist::Tracer::Closer cacheInsertCloser;
+ if (dnsResponse.ids.tracingEnabled) {
+ cacheInsertCloser = dnsResponse.ids.d_OTTracer->openSpan("packetCacheInsert", closer.getSpanID());
+ }
+ dnsResponse.ids.packetCache->insert(cacheKey, zeroScope ? boost::none : dnsResponse.ids.subnet, dnsResponse.ids.cacheFlags, dnsResponse.ids.dnssecOK ? *dnsResponse.ids.dnssecOK : false, dnsResponse.ids.qname, dnsResponse.ids.qtype, dnsResponse.ids.qclass, response, dnsResponse.ids.forwardedOverUDP, dnsResponse.getHeader()->rcode, dnsResponse.ids.tempFailureTTL);
+ }
const auto& chains = dnsdist::configuration::getCurrentRuntimeConfiguration().d_ruleChains;
const auto& cacheInsertedRespRuleActions = dnsdist::rules::getResponseRuleChain(chains, dnsdist::rules::ResponseRuleChain::CacheInsertedResponseRules);
if (!applyRulesToResponse(cacheInsertedRespRuleActions, dnsResponse)) {
bool processResponse(PacketBuffer& response, DNSResponse& dnsResponse, bool muted)
{
+ pdns::trace::dnsdist::Tracer::Closer closer;
+ if (dnsResponse.ids.tracingEnabled) {
+ closer = dnsResponse.ids.d_OTTracer->openSpan("processResponse");
+ }
+
const auto& chains = dnsdist::configuration::getCurrentRuntimeConfiguration().d_ruleChains;
const auto& respRuleActions = dnsdist::rules::getResponseRuleChain(chains, dnsdist::rules::ResponseRuleChain::ResponseRules);
static bool applyRulesToQuery(DNSQuestion& dnsQuestion, const timespec& now)
{
+ auto closer = dnsQuestion.ids.d_OTTracer->openSpan("applyRulesToQuery", dnsQuestion.ids.d_OTTracer->getLastSpanID());
if (g_rings.shouldRecordQueries()) {
g_rings.insertQuery(now, dnsQuestion.ids.origRemote, dnsQuestion.ids.qname, dnsQuestion.ids.qtype, dnsQuestion.getData().size(), *dnsQuestion.getHeader(), dnsQuestion.getProtocol());
}
static ServerPolicy::SelectedBackend selectBackendForOutgoingQuery(DNSQuestion& dnsQuestion, const ServerPool& serverPool)
{
+ auto closer = dnsQuestion.ids.d_OTTracer->openSpan("selectBackendForOutgoingQuery", dnsQuestion.ids.d_OTTracer->getLastSpanID());
+
const auto& policy = serverPool.policy != nullptr ? *serverPool.policy : *dnsdist::configuration::getCurrentRuntimeConfiguration().d_lbPolicy;
const auto& servers = serverPool.getServers();
- return policy.getSelectedBackend(servers, dnsQuestion);
+ auto selectedBackend = policy.getSelectedBackend(servers, dnsQuestion);
+
+ if (dnsQuestion.ids.tracingEnabled) {
+ dnsQuestion.ids.d_OTTracer->setSpanAttribute(closer.getSpanID(), "backend.name", AnyValue{selectedBackend->getNameWithAddr()});
+ dnsQuestion.ids.d_OTTracer->setSpanAttribute(closer.getSpanID(), "backend.id", AnyValue{boost::uuids::to_string(selectedBackend->getID())});
+ }
+
+ return selectedBackend;
}
// NOLINTNEXTLINE(readability-function-cognitive-complexity): refactoring will be done in https://github.com/PowerDNS/pdns/pull/16124
ProcessQueryResult processQuery(DNSQuestion& dnsQuestion, std::shared_ptr<DownstreamState>& selectedBackend)
{
- const uint16_t queryId = ntohs(dnsQuestion.getHeader()->id);
+ auto closer = dnsQuestion.ids.d_OTTracer->openSpan("processQuery", dnsQuestion.ids.d_OTTracer->getLastSpanID());
+ const uint16_t queryId = ntohs(dnsQuestion.getHeader()->id);
try {
/* we need an accurate ("real") value for the response and
to store into the IDS, but not for insertion into the
bool assignOutgoingUDPQueryToBackend(std::shared_ptr<DownstreamState>& downstream, uint16_t queryID, DNSQuestion& dnsQuestion, PacketBuffer& query, bool actuallySend)
{
+ auto closer = dnsQuestion.ids.d_OTTracer->openSpan("assignOutgoingUDPQueryToBackend", dnsQuestion.ids.d_OTTracer->getLastSpanID());
+
bool doh = dnsQuestion.ids.du != nullptr;
bool failed = false;
assert(responsesVect == nullptr || (queuedResponses != nullptr && respIOV != nullptr && respCBuf != nullptr));
uint16_t queryId = 0;
InternalQueryState ids;
+
+ auto closer = ids.d_OTTracer->openSpan("processUDPQuery");
+
ids.cs = &clientState;
ids.origRemote = remote;
ids.hopRemote = remote;
src_dir / 'dnsdist-metrics.cc',
src_dir / 'dnsdist-nghttp2.cc',
src_dir / 'dnsdist-nghttp2-in.cc',
+ src_dir / 'dnsdist-opentelemetry.cc',
src_dir / 'dnsdist-protobuf.cc',
src_dir / 'dnsdist-protocols.cc',
src_dir / 'dnsdist-proxy-protocol.cc',
src_dir / 'libssl.cc',
src_dir / 'misc.cc',
src_dir / 'protozero.cc',
+ src_dir / 'protozero-trace.cc',
src_dir / 'proxy-protocol.cc',
src_dir / 'qtype.cc',
src_dir / 'remote_logger.cc',
--- /dev/null
+../protozero-trace.cc
\ No newline at end of file
--- /dev/null
+../protozero-trace.hh
\ No newline at end of file
dns_random(span.data(), span.size());
}
+inline SpanID randomSpanID()
+{
+ SpanID ret;
+ random(ret);
+ return ret;
+}
+
inline void clear(TraceID& trace)
{
trace.fill(0);