]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
rec: add EDE and OT TraceID to protobuf
authorOtto Moerbeek <otto.moerbeek@open-xchange.com>
Wed, 17 Sep 2025 13:32:06 +0000 (15:32 +0200)
committerOtto Moerbeek <otto.moerbeek@open-xchange.com>
Wed, 17 Sep 2025 13:38:53 +0000 (15:38 +0200)
Signed-off-by: Otto Moerbeek <otto.moerbeek@open-xchange.com>
contrib/ProtobufLogger.py
pdns/dnsmessage.proto
pdns/protozero-trace.hh
pdns/protozero.hh
pdns/recursordist/pdns_recursor.cc
pdns/recursordist/rec-main.cc
pdns/recursordist/rec-main.hh
pdns/recursordist/rec-tcp.cc

index c056150c1bc2cb9447d372723f181783da69756b..1b035e0e9869608030c9492ba291e49aa259c84e 100644 (file)
@@ -304,12 +304,23 @@ class PDNSPBConnHandler(object):
         if msg.HasField('ednsVersion'):
             ednsVersion = "0x%08X" % socket.ntohl(msg.ednsVersion)
 
+        ede = "N/A"
+        if msg.HasField('ede'):
+            ede = str(msg.ede)
+        edeText = "N/A"
+        if msg.HasField('edeText'):
+            edeText = msg.edeText
+
         openTelemetryData = "N/A"
         if opentelemetryAvailable and msg.HasField('openTelemetryData'):
             openTelemetryData = str(len(msg.openTelemetryData))
 
+        openTelemetryTraceID = "N/A"
+        if msg.HasField('openTelemetryTraceID'):
+            openTelemetryTraceID = binascii.hexlify(msg.openTelemetryTraceID)
+
         print('[%s] %s of size %d: %s%s%s -> %s%s(%s) id: %d uuid: %s%s '
-                  'requestorid: %s deviceid: %s devicename: %s serverid: %s nod: %s workerId: %s pcCacheHit: %s outgoingQueries: %s headerFlags: %s ednsVersion: %s openTelemetryData: len %s' %
+                  'requestorid: %s deviceid: %s devicename: %s serverid: %s nod: %s workerId: %s pcCacheHit: %s outgoingQueries: %s headerFlags: %s ednsVersion: %s ede: %s edeText: %s openTelemetryData: len %s otTraceID: %s' %
               (datestr,
                typestr,
                msg.inBytes,
@@ -332,7 +343,10 @@ class PDNSPBConnHandler(object):
                outgoingQs,
                headerFlags,
                ednsVersion,
-               openTelemetryData))
+               ede,
+               edeText,
+               openTelemetryData,
+               openTelemetryTraceID))
 
         for mt in msg.meta:
             values = ''
index cfc721f2f25efc269cbd53e4d6c0b86599609dda..f459e993d74ed11ea552e41b83abc42a29cdddc7 100644 (file)
@@ -193,6 +193,9 @@ message PBDNSMessage {
   optional uint32 headerFlags = 28;             // Flags field in wire format, 16 bits used
   optional uint32 ednsVersion = 29;             // EDNS version and flags in wire format, see https://www.rfc-editor.org/rfc/rfc6891.html#section-6.1.3
   optional bytes openTelemetryData = 30;        // Protobuf encoded Open Telemetry Data, see https://github.com/open-telemetry/opentelemetry-proto/blob/main/opentelemetry/proto/trace/v1/trace.proto
+  optional uint32 ede = 31;                     // EDNS error code, actually 16 bits
+  optional string edeText = 32;                 // EDNS error text
+  optional bytes openTelemetryTraceID = 33;     // OpenTelemetry TraceID
 }
 
 message PBDNSMessageList {
index a915dc331aa0357e1a2d52a6de9da03a887c4cbc..9bcbb5ec06ca727c7db61e49b12ac8084bc0901d 100644 (file)
@@ -226,6 +226,8 @@ struct InstrumentationScope
 using TraceID = std::array<uint8_t, 16>;
 using SpanID = std::array<uint8_t, 8>;
 
+constexpr TraceID s_emptyTraceID = {};
+
 inline void random(TraceID& trace)
 {
   dns_random(trace.data(), trace.size());
index 3b42e5fc74fb4a35b0ed061a25083fafff723b03..744e3bcb93e1340e933f2353aaf4943c2f2c448a 100644 (file)
@@ -104,6 +104,9 @@ namespace ProtoZero
       headerFlags = 28,
       ednsVersion = 29,
       openTelemetryData = 30,
+      ede = 31,
+      edeText = 32,
+      openTelemetryTraceID = 33,
     };
     enum class QuestionField : protozero::pbf_tag_type
     {
@@ -322,6 +325,23 @@ namespace ProtoZero
       }
     }
 
+    void setEDE(const uint16_t ede)
+    {
+      add_uint32(d_message, Field::ede, ede);
+    }
+
+    void setEDEText(const std::string edeText)
+    {
+      if (!edeText.empty()) {
+        add_string(d_message, Field::edeText, edeText);
+      }
+    }
+
+    void setOpenTelemtryTraceID(const std::array<uint8_t, 16>& traceID)
+    {
+      add_bytes(d_message, Field::openTelemetryTraceID, reinterpret_cast<const char*>(traceID.data()), traceID.size()); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast): it's the API
+    }
+
     void startResponse()
     {
       d_response = protozero::pbf_writer{d_message, static_cast<protozero::pbf_tag_type>(Field::response)};
index 4ac18ec19bdac6906527d342a35c20969af97ad3..fd3ceb01caf5c0cfb49010f5758f0f7087e3bc2c 100644 (file)
@@ -1618,6 +1618,7 @@ void startDoResolve(void* arg) // NOLINT(readability-function-cognitive-complexi
       }
     }
 
+    std::optional<EDNSExtendedError> eee;
     if (haveEDNS) {
       auto state = resolver.getValidationState();
       if (comboWriter->d_extendedErrorCode || resolver.d_extendedError || (SyncRes::s_addExtendedResolutionDNSErrors && vStateIsBogus(state))) {
@@ -1681,13 +1682,10 @@ void startDoResolve(void* arg) // NOLINT(readability-function-cognitive-complexi
             throw std::runtime_error("Bogus validation state not handled: " + vStateToString(state));
           }
         }
+        eee.emplace(EDNSExtendedError{static_cast<uint16_t>(code), std::move(extra)});
 
-        EDNSExtendedError eee;
-        eee.infoCode = static_cast<uint16_t>(code);
-        eee.extraText = std::move(extra);
-
-        if (packetWriter.size() < maxanswersize && (maxanswersize - packetWriter.size()) >= (EDNSOptionCodeSize + EDNSOptionLengthSize + sizeof(eee.infoCode) + eee.extraText.size())) {
-          returnedEdnsOptions.emplace_back(EDNSOptionCode::EXTENDEDERROR, makeEDNSExtendedErrorOptString(eee));
+        if (packetWriter.size() < maxanswersize && (maxanswersize - packetWriter.size()) >= (EDNSOptionCodeSize + EDNSOptionLengthSize + sizeof(eee->infoCode) + eee->extraText.size())) {
+          returnedEdnsOptions.emplace_back(EDNSOptionCode::EXTENDEDERROR, makeEDNSExtendedErrorOptString(*eee));
         }
       }
 
@@ -1750,6 +1748,10 @@ void startDoResolve(void* arg) // NOLINT(readability-function-cognitive-complexi
       pbMessage.setValidationState(resolver.getValidationState());
       // See if we want to store the policyTags into the PC
       addPolicyTagsToPBMessageIfNeeded(*comboWriter, pbMessage);
+      if (eee) {
+        pbMessage.setEDE(eee->infoCode);
+        pbMessage.setEDEText(eee->extraText);
+      }
 
       // Take s snap of the current protobuf buffer state to store in the PC
       pbDataForCache = boost::make_optional(RecursorPacketCache::PBData{
@@ -1863,6 +1865,10 @@ void startDoResolve(void* arg) // NOLINT(readability-function-cognitive-complexi
         string otData = otTrace.encode();
         pbMessage.setOpenTelemetryData(otData);
       }
+      // Currently only set if an OT trace is generated
+      if (resolver.d_otTrace.trace_id != pdns::trace::s_emptyTraceID) {
+        pbMessage.setOpenTelemtryTraceID(resolver.d_otTrace.trace_id);
+      }
       if (comboWriter->d_logResponse) {
         protobufLogResponse(pbMessage);
       }
@@ -2268,7 +2274,7 @@ static string* doProcessUDPQuestion(const std::string& question, const ComboAddr
     RecursorPacketCache::OptPBData pbData{boost::none};
     if (t_protobufServers.servers) {
       if (logQuery && !(luaconfsLocal->protobufExportConfig.taggedOnly && policyTags.empty())) {
-        protobufLogQuery(luaconfsLocal, uniqueId, source, destination, mappedSource, ednssubnet.getSource(), false, question.size(), qname, qtype, qclass, policyTags, requestorId, deviceId, deviceName, meta, ednsVersion, *dnsheader);
+        protobufLogQuery(luaconfsLocal, uniqueId, source, destination, mappedSource, ednssubnet.getSource(), false, question.size(), qname, qtype, qclass, policyTags, requestorId, deviceId, deviceName, meta, ednsVersion, *dnsheader, otTrace.trace_id);
       }
     }
 
index 11773172c72fb0af5bebb1d48a5760b89bca6fd7..55149fa15c072e6516bea3022bf9c2c4d83267bf 100644 (file)
@@ -502,7 +502,7 @@ bool checkOutgoingProtobufExport(LocalStateHolder<LuaConfigItems>& luaconfsLocal
   return true;
 }
 
-void protobufLogQuery(LocalStateHolder<LuaConfigItems>& luaconfsLocal, const boost::uuids::uuid& uniqueId, const ComboAddress& remote, const ComboAddress& local, const ComboAddress& mappedSource, const Netmask& ednssubnet, bool tcp, size_t len, const DNSName& qname, uint16_t qtype, uint16_t qclass, const std::unordered_set<std::string>& policyTags, const std::string& requestorId, const std::string& deviceId, const std::string& deviceName, const std::map<std::string, RecursorLua4::MetaValue>& meta, const boost::optional<uint32_t>& ednsVersion, const dnsheader& header)
+void protobufLogQuery(LocalStateHolder<LuaConfigItems>& luaconfsLocal, const boost::uuids::uuid& uniqueId, const ComboAddress& remote, const ComboAddress& local, const ComboAddress& mappedSource, const Netmask& ednssubnet, bool tcp, size_t len, const DNSName& qname, uint16_t qtype, uint16_t qclass, const std::unordered_set<std::string>& policyTags, const std::string& requestorId, const std::string& deviceId, const std::string& deviceName, const std::map<std::string, RecursorLua4::MetaValue>& meta, const boost::optional<uint32_t>& ednsVersion, const dnsheader& header, const pdns::trace::TraceID& traceID)
 {
   auto log = g_slog->withName("pblq");
 
@@ -543,6 +543,9 @@ void protobufLogQuery(LocalStateHolder<LuaConfigItems>& luaconfsLocal, const boo
   if (ednsVersion) {
     msg.setEDNSVersion(*ednsVersion);
   }
+  if (traceID != pdns::trace::s_emptyTraceID) {
+    msg.setOpenTelemtryTraceID(traceID);
+  }
 
   std::string strMsg(msg.finishAndMoveBuf());
   for (auto& server : *t_protobufServers.servers) {
@@ -636,6 +639,9 @@ void protobufLogResponse(const DNSName& qname, QType qtype,
     auto trace = pdns::trace::TracesData::boilerPlate("rec", qname.toLogString() + '/' + qtype.toString(), eventTrace.convertToOT(otTrace));
     pbMessage.setOpenTelemetryData(trace.encode());
   }
+  if (otTrace.trace_id != pdns::trace::s_emptyTraceID) {
+    pbMessage.setOpenTelemtryTraceID(otTrace.trace_id);
+  }
   pbMessage.addPolicyTags(policyTags);
 
   protobufLogResponse(pbMessage);
index 9288002034e18ad99e9d8dd352442c59018c2ea7..d378e14a0f1d567e3ef43d61d1264451cee5de95 100644 (file)
@@ -625,7 +625,7 @@ bool checkFrameStreamExport(LocalStateHolder<LuaConfigItems>& luaconfsLocal, con
 #endif
 void getQNameAndSubnet(const std::string& question, DNSName* dnsname, uint16_t* qtype, uint16_t* qclass,
                        bool& foundECS, EDNSSubnetOpts* ednssubnet, EDNSOptionViewMap* options, boost::optional<uint32_t>& ednsVersion);
-void protobufLogQuery(LocalStateHolder<LuaConfigItems>& luaconfsLocal, const boost::uuids::uuid& uniqueId, const ComboAddress& remote, const ComboAddress& local, const ComboAddress& mappedSource, const Netmask& ednssubnet, bool tcp, size_t len, const DNSName& qname, uint16_t qtype, uint16_t qclass, const std::unordered_set<std::string>& policyTags, const std::string& requestorId, const std::string& deviceId, const std::string& deviceName, const std::map<std::string, RecursorLua4::MetaValue>& meta, const boost::optional<uint32_t>& ednsVersion, const dnsheader& header);
+void protobufLogQuery(LocalStateHolder<LuaConfigItems>& luaconfsLocal, const boost::uuids::uuid& uniqueId, const ComboAddress& remote, const ComboAddress& local, const ComboAddress& mappedSource, const Netmask& ednssubnet, bool tcp, size_t len, const DNSName& qname, uint16_t qtype, uint16_t qclass, const std::unordered_set<std::string>& policyTags, const std::string& requestorId, const std::string& deviceId, const std::string& deviceName, const std::map<std::string, RecursorLua4::MetaValue>& meta, const boost::optional<uint32_t>& ednsVersion, const dnsheader& header, const pdns::trace::TraceID& traceID);
 bool isAllowNotifyForZone(DNSName qname);
 bool checkForCacheHit(bool qnameParsed, unsigned int tag, const string& data,
                       DNSName& qname, uint16_t& qtype, uint16_t& qclass,
index 6d26f2b417ee8890ccb8caf136d9fd7d646e1446..b5e23140d9f0ec76b737d9677dcf2c3a8f173111 100644 (file)
@@ -274,7 +274,7 @@ static void doProtobufLogQuery(bool logQuery, LocalStateHolder<LuaConfigItems>&
 {
   try {
     if (logQuery && !(luaconfsLocal->protobufExportConfig.taggedOnly && comboWriter->d_policyTags.empty())) {
-      protobufLogQuery(luaconfsLocal, comboWriter->d_uuid, comboWriter->d_source, comboWriter->d_destination, comboWriter->d_mappedSource, comboWriter->d_ednssubnet.getSource(), true, conn->qlen, qname, qtype, qclass, comboWriter->d_policyTags, comboWriter->d_requestorId, comboWriter->d_deviceId, comboWriter->d_deviceName, comboWriter->d_meta, ednsVersion, *dnsheader);
+      protobufLogQuery(luaconfsLocal, comboWriter->d_uuid, comboWriter->d_source, comboWriter->d_destination, comboWriter->d_mappedSource, comboWriter->d_ednssubnet.getSource(), true, conn->qlen, qname, qtype, qclass, comboWriter->d_policyTags, comboWriter->d_requestorId, comboWriter->d_deviceId, comboWriter->d_deviceName, comboWriter->d_meta, ednsVersion, *dnsheader, comboWriter->d_otTrace.trace_id);
     }
   }
   catch (const std::exception& e) {