type: "bool"
default: "false"
description: "Remove any existing TRACEPARENT EDNS option from the query. When use_incoming_traceid is set to true, the ID will be picked set before removing the option"
- - name: "downstream_edns_traceparent_option_code"
- type: "u16"
- default: "0"
- description: "Set to the EDNS option code to add the TRACEPARENT option to the EDNS options of the query forwarded to the downstream server. When ``strip_incoming_traceparent`` is ``false`` and this option is not set, any TRACEPARENT option in the original query will be sent downstream unaltered"
+ - name: "send_downstream_traceparent"
+ type: "bool"
+ default: "false"
+ description: "Set to true to add (or update) the TRACEPARENT option in the EDNS options of the query forwarded to the downstream server. When ``strip_incoming_traceparent`` is ``false`` and this option is ``false``, any TRACEPARENT option in the original query will be sent downstream unaltered"
- name: "SNMPTrap"
description: "Send an SNMP trap, adding the message string as the query description. Subsequent rules are processed after this action"
parameters:
{
public:
SetTraceAction(SetTraceActionConfiguration& config) :
- d_loggers(config.remote_loggers), d_incomingTraceparentOptionCode(config.incomingTraceparentOptionCode), d_downstreamTraceparentOptionCode(config.downstreamTraceparentOptionCode), d_value{config.value}, d_useIncomingTraceparent(config.useIncomingTraceparent), d_stripIncomingTraceparent(config.stripIncomingTraceparent) {};
+ d_loggers(config.remote_loggers), d_traceparentOptionCode(config.traceparentOptionCode), d_value{config.value}, d_useIncomingTraceparent(config.useIncomingTraceparent), d_stripIncomingTraceparent(config.stripIncomingTraceparent), d_sendDownstreamTraceparent(config.sendDownstreamTraceparent) {};
DNSAction::Action operator()([[maybe_unused]] DNSQuestion* dnsquestion, [[maybe_unused]] std::string* ruleresult) const override
{
tracer->setRootSpanAttribute("query.remote.address", AnyValue{dnsquestion->ids.origRemote.toString()});
tracer->setRootSpanAttribute("query.remote.port", AnyValue{dnsquestion->ids.origRemote.getPort()});
- if (d_downstreamTraceparentOptionCode != 0) {
- dnsquestion->ids.sendTraceParentToDownstreamID = d_downstreamTraceparentOptionCode;
+ if (d_sendDownstreamTraceparent) {
+ dnsquestion->ids.sendTraceParentToDownstreamID = d_traceparentOptionCode;
}
if (!d_useIncomingTraceparent && !d_stripIncomingTraceparent) {
if (d_useIncomingTraceparent) {
pdns::trace::TraceID traceID;
pdns::trace::SpanID spanID;
- if (pdns::trace::extractOTraceIDs(*(dnsquestion->ednsOptions), EDNSOptionCode::EDNSOptionCodeEnum(d_incomingTraceparentOptionCode), traceID, spanID)) {
+ if (pdns::trace::extractOTraceIDs(*(dnsquestion->ednsOptions), EDNSOptionCode::EDNSOptionCodeEnum(d_traceparentOptionCode), traceID, spanID)) {
tracer->setTraceID(traceID);
if (spanID != pdns::trace::s_emptySpanID) {
tracer->setRootSpanID(spanID);
}
size_t existingOptLen = optLen;
- removeEDNSOptionFromOPT(reinterpret_cast<char*>(&dnsquestion->getMutableData().at(optStart)), &optLen, d_incomingTraceparentOptionCode);
+ removeEDNSOptionFromOPT(reinterpret_cast<char*>(&dnsquestion->getMutableData().at(optStart)), &optLen, d_traceparentOptionCode);
dnsquestion->getMutableData().resize(dnsquestion->getData().size() - (existingOptLen - optLen));
// Ensure the EDNS Option View is not out of date
dnsquestion->ednsOptions.reset();
private:
std::vector<std::shared_ptr<RemoteLoggerInterface>> d_loggers;
- short unsigned int d_incomingTraceparentOptionCode;
- short unsigned int d_downstreamTraceparentOptionCode;
+ short unsigned int d_traceparentOptionCode;
bool d_value;
bool d_useIncomingTraceparent;
bool d_stripIncomingTraceparent;
+ bool d_sendDownstreamTraceparent;
};
#endif
struct SetTraceActionConfiguration
{
std::vector<std::shared_ptr<RemoteLoggerInterface>> remote_loggers;
- std::uint16_t incomingTraceparentOptionCode = 0;
- std::uint16_t downstreamTraceparentOptionCode = 0;
+ std::uint16_t traceparentOptionCode = 65500;
bool value = false;
bool useIncomingTraceparent = false;
bool stripIncomingTraceparent = false;
+ bool sendDownstreamTraceparent = false;
};
std::shared_ptr<DNSAction> getSetTraceAction(SetTraceActionConfiguration& config);
#endif /* DISABLE_PROTOBUF */
dnsdist::actions::SetTraceActionConfiguration actionConfig{
.remote_loggers = std::move(loggers),
- .incomingTraceparentOptionCode = config.traceparent_edns_option_code,
- .downstreamTraceparentOptionCode = config.downstream_edns_traceparent_option_code,
+ .traceparentOptionCode = config.traceparent_edns_option_code,
.value = config.value,
.useIncomingTraceparent = config.use_incoming_traceparent,
.stripIncomingTraceparent = config.strip_incoming_traceparent,
+ .sendDownstreamTraceparent = config.send_downstream_traceparent,
};
auto action = dnsdist::actions::getSetTraceAction(actionConfig);
}
}
config.remote_loggers = std::move(loggers);
- if (getOptionalValue<uint16_t>(options, "incomingTraceparentOptionCode", config.incomingTraceparentOptionCode) < 0) {
- throw std::runtime_error("incomingTraceparentOptionCode in SetTraceAction is not a number");
+ if (getOptionalValue<uint16_t>(options, "traceparentOptionCode", config.traceparentOptionCode) < 0) {
+ throw std::runtime_error("TraceparentOptionCode in SetTraceAction is not a number");
}
- if (config.useIncomingTraceparent == 0) {
- config.useIncomingTraceparent = 65500;
+ if (config.traceparentOptionCode == 0) {
+ config.traceparentOptionCode = EDNSOptionCode::TRACEPARENT;
}
- if (getOptionalValue<uint16_t>(options, "downstreamTraceparentOptionCode", config.downstreamTraceparentOptionCode) < 0) {
- throw std::runtime_error("downstreamTraceparentOptionCode in SetTraceAction is not a number");
+ if (getOptionalValue<bool>(options, "sendDownstreamTraceparent", config.sendDownstreamTraceparent) < 0) {
+ throw std::runtime_error("sendDownstreamTraceparent in SetTraceAction is not a bool");
}
if (getOptionalValue<bool>(options, "useIncomingTraceparent", config.useIncomingTraceparent) < 0) {
throw std::runtime_error("useIncomingTraceparent in SetTraceAction is not a bool");
Options:
- * ``remoteLoggers``: A table of :func:`remoteLogger <newRemoteLogger>` objects to send the traces to. Note that these log messages are empty apart from the trace data.
+ * ``remoteLoggers``: A table of :func:`remoteLogger <newRemoteLogger>` objects to send the traces to. Note that these log messages will be empty, apart from the trace data.
* ``useIncomingTraceparent``: boolean, default false. Use the information in the TRACEPARENT EDNS option (if any) from the query as the Trace ID and initial Span ID.
* ``stripIncomingTraceparent``: boolean, default false. Remove the TRACEPARENT EDNS option from the DNS query so it is not passed to the backend server.
- * ``incomingTraceparentOptionCode``: integer, default 65500. The EDNS option code for TRACEPARENT in the incoming query.
- * ``downstreamTraceparentOptionCode``: integer, default unset. When set, a TRACEPARENT EDNS option is added to the downstream query with the active Trace ID and the last Span ID of the trace.
+ * ``traceparentOptionCode``: integer, default 65500. The EDNS option code for TRACEPARENT EDNS option.
+ * ``sendDownstreamTraceparent``: boolean, default false. When true, a TRACEPARENT EDNS option is added to the downstream query with the active Trace ID and the last Span ID of the trace.
.. function:: SkipCacheAction()
When storing traces, it is beneficial to correlate traces of the same query through different applications.
The `PowerDNS Recursor <https://doc.powerdns.com/recursor>`__ (since 5.3.0) supports the experimental `TRACEPARENT <https://github.com/PowerDNS/draft-edns-otel-trace-ids>`__ EDNS option to pass the trace identifier.
-This can be easily achieved by adding the `downstream_edns_traceparent_option_code` option with the desired EDNS OptionCode.
+This can be easily achieved by adding the `send_downstream_traceparent` option with the desired EDNS OptionCode.
.. code-block:: yaml
action:
type: SetTrace
value: true
- downstream_edns_traceparent_option_code: 65500
+ send_downstream_traceparent: true
Accepting TRACEPARENT from upstream servers
===========================================
action:
type: SetTrace
value: true
- downstream_edns_traceparent_option_code: 65500
+ send_downstream_traceparent: true
use_incoming_traceparent: true
ottrace.data += binascii.a2b_hex(traceID)
if spanID != "":
ottrace.data += binascii.a2b_hex(spanID)
- ottrace.data += b"\x00" # flags
+ ottrace.data += b"\x00" # flags
query = dns.message.make_query(
name, "A", "IN", use_edns=True, options=[ottrace]
)
response.answer.append(rrset)
if useTCP:
- (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response)
+ receivedQuery, receivedResponse = self.sendTCPQuery(query, response)
else:
- (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
+ receivedQuery, receivedResponse = self.sendUDPQuery(query, response)
if querySentByDNSDist:
self.assertTrue(receivedQuery)
)
if useTCP:
- (_, receivedResponse) = self.sendTCPQuery(query, response=None)
+ _, receivedResponse = self.sendTCPQuery(query, response=None)
else:
- (_, receivedResponse) = self.sendUDPQuery(query, response=None)
+ _, receivedResponse = self.sendUDPQuery(query, response=None)
self.assertIsNotNone(receivedResponse)
# If we stripped the OpenTelemetry Trace ID from the query, we should not get a SERVFAIL
print(request)
response = dns.message.make_response(request)
- traceparent : dns.edns.Option|None = next((i for i in request.options if i.otype == 65500), None)
+ traceparent: dns.edns.Option | None = next(
+ (i for i in request.options if i.otype == 65500), None
+ )
print(traceparent)
return response.to_wire()
-
class TestOpenTelemetryTracingSendTraceparentDownstream(
DNSDistOpenTelemetryProtobufTest
):
action:
type: SetTrace
value: true
- downstream_edns_traceparent_option_code: 65500
+ send_downstream_traceparent: true
"""
@classmethod
def doQuery(self, useTCP=False):
name = "query.ot.tests.powerdns.com."
- query = dns.message.make_query(
- name, "A", "IN", use_edns=True
- )
+ query = dns.message.make_query(name, "A", "IN", use_edns=True)
if useTCP:
- (_, receivedResponse) = self.sendTCPQuery(query, response=None)
+ _, receivedResponse = self.sendTCPQuery(query, response=None)
else:
- (_, receivedResponse) = self.sendUDPQuery(query, response=None)
+ _, receivedResponse = self.sendUDPQuery(query, response=None)
self.assertIsNotNone(receivedResponse)
# If we stripped the OpenTelemetry Trace ID from the query, we should not get a SERVFAIL
def testSetDownstreamTraceparentTCP(self):
self.doQuery(True)
+
class TestOpenTelemetryTracingSendTraceparentDownstreamLua(
TestOpenTelemetryTracingSendTraceparentDownstream
):
rl = newRemoteLogger('127.0.0.1:%d')
setOpenTelemetryTracing(true)
-addAction(AllRule(), SetTraceAction(true, {remoteLoggers={rl}, downstreamTraceparentOptionCode=65500}), {name="Enable tracing"})
+addAction(AllRule(), SetTraceAction(true, {remoteLoggers={rl}, sendDownstreamTraceparent=true}), {name="Enable tracing"})
addResponseAction(AllRule(), RemoteLogResponseAction(rl), {name="Do PB logging"})
"""
action:
type: SetTrace
value: true
- downstream_edns_traceparent_option_code: 65500
+ send_downstream_traceparent: true
webserver:
listen_addresses:
#!/usr/bin/env python
-import dns
import selectors
import socket
import ssl
-import requests
import struct
import sys
import threading
import time
+import dns
+import requests
+
+from dnsdistdohtests import DNSDistDOHTest
from dnsdisttests import DNSDistTest, pickAvailablePort
from proxyprotocol import ProxyProtocol
-from proxyprotocolutils import ProxyProtocolUDPResponder, ProxyProtocolTCPResponder
-from dnsdistdohtests import DNSDistDOHTest
+from proxyprotocolutils import (ProxyProtocolTCPResponder,
+ ProxyProtocolUDPResponder)
# Python2/3 compatibility hacks
try:
return DNSAction.None
end
- addAction(AllRule(), SetTraceAction(true, {downstreamTraceparentOptionCode=65500}), {name="Enable tracing"})
+ addAction(AllRule(), SetTraceAction(true, {sendDownstreamTraceparent=true}), {name="Enable tracing"})
addAction("values-lua.proxy.tests.powerdns.com.", LuaAction(addValues))
addAction("values-action.proxy.tests.powerdns.com.", SetProxyProtocolValuesAction({ ["1"]="dnsdist", ["255"]="proxy-protocol"}))
addAction("random-values.proxy.tests.powerdns.com.", LuaAction(addRandomValue))