* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
+#include <memory>
#include <optional>
#include <unordered_map>
+#include <utility>
#include "dnsdist-actions-factory.hh"
public:
// this action does not stop the processing
RemoteLogResponseAction(RemoteLogActionConfiguration& config) :
- d_tagsToExport(std::move(config.tagsToExport)), d_metas(std::move(config.metas)), d_logger(config.logger), d_alterFunc(std::move(config.alterResponseFunc)), d_serverID(config.serverID), d_ipEncryptKey(config.ipEncryptKey), d_ipEncryptMethod(config.ipEncryptMethod), d_exportExtendedErrorsToMeta(std::move(config.exportExtendedErrorsToMeta)), d_includeCNAME(config.includeCNAME)
+ d_tagsToExport(std::move(config.tagsToExport)), d_metas(std::move(config.metas)), d_logger(config.logger), d_alterFunc(std::move(config.alterResponseFunc)), d_serverID(config.serverID), d_ipEncryptKey(config.ipEncryptKey), d_ipEncryptMethod(config.ipEncryptMethod), d_exportExtendedErrorsToMeta(std::move(config.exportExtendedErrorsToMeta)), d_includeCNAME(config.includeCNAME), d_delay(config.delay)
{
if (!d_ipEncryptKey.empty() && d_ipEncryptMethod == "ipcrypt-pfx") {
d_ipcrypt2 = pdns::ipcrypt2::IPCrypt2(pdns::ipcrypt2::IPCryptMethod::pfx, d_ipEncryptKey);
(*d_alterFunc)(response, &message);
}
- static thread_local std::string data;
- data.clear();
- message.serialize(data);
- if (!response->ids.d_rawProtobufContent.empty()) {
- data.insert(data.end(), response->ids.d_rawProtobufContent.begin(), response->ids.d_rawProtobufContent.end());
+ if (d_delay) {
+ response->ids.delayedResponseMsgs.emplace_back(std::unique_ptr<DNSDistProtoBufMessage>(std::make_unique<DNSDistProtoBufMessage>(message)), std::shared_ptr<RemoteLoggerInterface>(d_logger));
+ }
+ else {
+ static thread_local std::string data;
+ data.clear();
+ message.serialize(data);
+ if (!response->ids.d_rawProtobufContent.empty()) {
+ data.insert(data.end(), response->ids.d_rawProtobufContent.begin(), response->ids.d_rawProtobufContent.end());
+ }
+ d_logger->queueData(data);
}
- d_logger->queueData(data);
return Action::None;
}
std::optional<pdns::ipcrypt2::IPCrypt2> d_ipcrypt2{std::nullopt};
std::optional<std::string> d_exportExtendedErrorsToMeta{std::nullopt};
bool d_includeCNAME;
+ bool d_delay{false};
};
#endif /* DISABLE_PROTOBUF */
std::string ipEncryptMethod{"legacy"};
std::optional<std::string> exportExtendedErrorsToMeta{std::nullopt};
bool includeCNAME{false};
+ bool delay{false};
};
std::shared_ptr<DNSAction> getRemoteLogAction(RemoteLogActionConfiguration& config);
std::shared_ptr<DNSResponseAction> getRemoteLogResponseAction(RemoteLogActionConfiguration& config);
if (dnsdist::configuration::yaml::getLuaFunctionFromConfiguration(alterFunc, config.alter_function_name, config.alter_function_code, config.alter_function_file, "remote log response action")) {
actionConfig.alterResponseFunc = std::move(alterFunc);
}
+ actionConfig.delay = config.delay;
auto action = dnsdist::actions::getRemoteLogResponseAction(actionConfig);
return newDNSResponseActionWrapper(std::move(action), config.name);
#endif
#include "dnsdist-opentelemetry.hh"
#include "uuid-utils.hh"
+#ifndef DISABLE_PROTOBUF
+#include "dnsdist-protobuf.hh"
+#include "remote_logger.hh"
+#endif
+
struct ClientState;
struct DOHUnitInterface;
struct DOQUnit;
std::unique_ptr<QTag> qTag{nullptr}; // 8
std::unique_ptr<PacketBuffer> d_packet{nullptr}; // Initial packet, so we can restart the query from the response path if needed // 8
std::unique_ptr<ProtoBufData> d_protoBufData{nullptr};
+#ifndef DISABLE_PROTOBUF
+ std::vector<std::pair<std::unique_ptr<DNSDistProtoBufMessage>, std::shared_ptr<RemoteLoggerInterface>>> delayedResponseMsgs;
+#endif
std::unique_ptr<EDNSExtendedError> d_extendedError{nullptr};
boost::optional<uint32_t> tempFailureTTL{boost::none}; // 8
ClientState* cs{nullptr}; // 8
type: "Vec<ProtoBufMetaConfiguration>"
default: true
description: "A list of ``name``=``key`` pairs, for meta-data to be added to Protocol Buffer message"
+ - name: "delay"
+ type: "bool"
+ default: "false"
+ description: "Delay sending the protobuf message until after the response has been sent to the client. Useful when using OpenTelemetry Tracing"
- name: "SetEDNSOption"
description: "Add arbitrary EDNS option and data to the response. Any existing EDNS content with the same option code will be replaced. Subsequent rules are processed after this action"
parameters:
void handleResponseSent(const InternalQueryState& ids, double udiff, const ComboAddress& client, const ComboAddress& backend, unsigned int size, const dnsheader& cleartextDH, dnsdist::Protocol outgoingProtocol, bool fromBackend)
{
handleResponseSent(ids.qname, ids.qtype, udiff, client, backend, size, cleartextDH, outgoingProtocol, ids.protocol, fromBackend);
+
+#ifndef DISABLE_PROTOBUF
+ if (ids.tracingEnabled && !ids.delayedResponseMsgs.empty()) {
+ static thread_local std::string data;
+ for (auto const& msg_logger : ids.delayedResponseMsgs) {
+ data.clear();
+ msg_logger.first->serialize(data);
+ if (!ids.d_rawProtobufContent.empty()) {
+ data.insert(data.end(), ids.d_rawProtobufContent.begin(), ids.d_rawProtobufContent.end());
+ }
+ msg_logger.second->queueData(data);
+ }
+ }
+#endif
}
void handleResponseSent(const DNSName& qname, const QType& qtype, double udiff, const ComboAddress& client, const ComboAddress& backend, unsigned int size, const dnsheader& cleartextDH, dnsdist::Protocol outgoingProtocol, dnsdist::Protocol incomingProtocol, bool fromBackend)
action:
type: RemoteLog
logger_name: pblog
+ # Delay ensures that the PB message is sent
+ # after the response is sent to client, instead
+ # of immediately. This ensures all Trace Spans
+ # have proper end timestamps.
+ delay: true
Passing Trace ID and Span ID to downstream servers
==================================================