{ "latency-avg1000", MetricDefinition(PrometheusMetricType::gauge, "Average response latency in microseconds of the last 1000 packets")},
{ "latency-avg10000", MetricDefinition(PrometheusMetricType::gauge, "Average response latency in microseconds of the last 10000 packets")},
{ "latency-avg1000000", MetricDefinition(PrometheusMetricType::gauge, "Average response latency in microseconds of the last 1000000 packets")},
+ { "latency-tcp-avg100", MetricDefinition(PrometheusMetricType::gauge, "Average response latency, in microseconds, of the last 100 packets received over TCP")},
+ { "latency-tcp-avg1000", MetricDefinition(PrometheusMetricType::gauge, "Average response latency, in microseconds, of the last 1000 packets received over TCP")},
+ { "latency-tcp-avg10000", MetricDefinition(PrometheusMetricType::gauge, "Average response latency, in microseconds, of the last 10000 packets received over TCP")},
+ { "latency-tcp-avg1000000", MetricDefinition(PrometheusMetricType::gauge, "Average response latency, in microseconds, of the last 1000000 packets received over TCP")},
+ { "latency-dot-avg100", MetricDefinition(PrometheusMetricType::gauge, "Average response latency, in microseconds, of the last 100 packets received over DoT")},
+ { "latency-dot-avg1000", MetricDefinition(PrometheusMetricType::gauge, "Average response latency, in microseconds, of the last 1000 packets received over DoT")},
+ { "latency-dot-avg10000", MetricDefinition(PrometheusMetricType::gauge, "Average response latency, in microseconds, of the last 10000 packets received over DoT")},
+ { "latency-dot-avg1000000", MetricDefinition(PrometheusMetricType::gauge, "Average response latency, in microseconds, of the last 1000000 packets received over DoT")},
+ { "latency-doh-avg100", MetricDefinition(PrometheusMetricType::gauge, "Average response latency, in microseconds, of the last 100 packets received over DoH")},
+ { "latency-doh-avg1000", MetricDefinition(PrometheusMetricType::gauge, "Average response latency, in microseconds, of the last 1000 packets received over DoH")},
+ { "latency-doh-avg10000", MetricDefinition(PrometheusMetricType::gauge, "Average response latency, in microseconds, of the last 10000 packets received over DoH")},
+ { "latency-doh-avg1000000", MetricDefinition(PrometheusMetricType::gauge, "Average response latency, in microseconds, of the last 1000000 packets received over DoH")},
{ "uptime", MetricDefinition(PrometheusMetricType::gauge, "Uptime of the dnsdist process in seconds")},
{ "real-memory-usage", MetricDefinition(PrometheusMetricType::gauge, "Current memory usage in bytes")},
{ "noncompliant-queries", MetricDefinition(PrometheusMetricType::counter, "Number of queries dropped as non-compliant")},
return true;
}
-void doLatencyStats(double udiff)
+void doLatencyStats(dnsdist::Protocol protocol, double udiff)
{
- if(udiff < 1000) ++g_stats.latency0_1;
- else if(udiff < 10000) ++g_stats.latency1_10;
- else if(udiff < 50000) ++g_stats.latency10_50;
- else if(udiff < 100000) ++g_stats.latency50_100;
- else if(udiff < 1000000) ++g_stats.latency100_1000;
- else ++g_stats.latencySlow;
- g_stats.latencySum += udiff / 1000;
- ++g_stats.latencyCount;
-
- auto doAvg = [](double& var, double n, double weight) {
+ constexpr auto doAvg = [](double& var, double n, double weight) {
var = (weight -1) * var/weight + n/weight;
};
- doAvg(g_stats.latencyAvg100, udiff, 100);
- doAvg(g_stats.latencyAvg1000, udiff, 1000);
- doAvg(g_stats.latencyAvg10000, udiff, 10000);
- doAvg(g_stats.latencyAvg1000000, udiff, 1000000);
+ if (protocol == dnsdist::Protocol::DoUDP || protocol == dnsdist::Protocol::DNSCryptUDP) {
+ if (udiff < 1000) {
+ ++g_stats.latency0_1;
+ }
+ else if (udiff < 10000) {
+ ++g_stats.latency1_10;
+ }
+ else if (udiff < 50000) {
+ ++g_stats.latency10_50;
+ }
+ else if (udiff < 100000) {
+ ++g_stats.latency50_100;
+ }
+ else if (udiff < 1000000) {
+ ++g_stats.latency100_1000;
+ }
+ else {
+ ++g_stats.latencySlow;
+ }
+
+ g_stats.latencySum += udiff / 1000;
+ ++g_stats.latencyCount;
+
+ doAvg(g_stats.latencyAvg100, udiff, 100);
+ doAvg(g_stats.latencyAvg1000, udiff, 1000);
+ doAvg(g_stats.latencyAvg10000, udiff, 10000);
+ doAvg(g_stats.latencyAvg1000000, udiff, 1000000);
+ }
+ else if (protocol == dnsdist::Protocol::DoTCP || protocol == dnsdist::Protocol::DNSCryptTCP) {
+ doAvg(g_stats.latencyTCPAvg100, udiff, 100);
+ doAvg(g_stats.latencyTCPAvg1000, udiff, 1000);
+ doAvg(g_stats.latencyTCPAvg10000, udiff, 10000);
+ doAvg(g_stats.latencyTCPAvg1000000, udiff, 1000000);
+ }
+ else if (protocol == dnsdist::Protocol::DoT) {
+ doAvg(g_stats.latencyDoTAvg100, udiff, 100);
+ doAvg(g_stats.latencyDoTAvg1000, udiff, 1000);
+ doAvg(g_stats.latencyDoTAvg10000, udiff, 10000);
+ doAvg(g_stats.latencyDoTAvg1000000, udiff, 1000000);
+ }
+ else if (protocol == dnsdist::Protocol::DoH) {
+ doAvg(g_stats.latencyDoHAvg100, udiff, 100);
+ doAvg(g_stats.latencyDoHAvg1000, udiff, 1000);
+ doAvg(g_stats.latencyDoHAvg10000, udiff, 10000);
+ doAvg(g_stats.latencyDoHAvg1000000, udiff, 1000000);
+ }
}
bool responseContentMatches(const PacketBuffer& response, const DNSName& qname, const uint16_t qtype, const uint16_t qclass, const std::shared_ptr<DownstreamState>& remote, unsigned int& qnameWireLength)
return true;
}
-void handleResponseSent(const IDState& ids, double udiff, const ComboAddress& client, const ComboAddress& backend, unsigned int size, const dnsheader& cleartextDH, dnsdist::Protocol protocol)
+void handleResponseSent(const IDState& ids, double udiff, const ComboAddress& client, const ComboAddress& backend, unsigned int size, const dnsheader& cleartextDH, dnsdist::Protocol outgoingProtocol)
{
- handleResponseSent(ids.qname, ids.qtype, udiff, client, backend, size, cleartextDH, protocol);
+ handleResponseSent(ids.qname, ids.qtype, udiff, client, backend, size, cleartextDH, outgoingProtocol, ids.protocol);
}
-void handleResponseSent(const DNSName& qname, const QType& qtype, double udiff, const ComboAddress& client, const ComboAddress& backend, unsigned int size, const dnsheader& cleartextDH, dnsdist::Protocol protocol)
+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)
{
struct timespec ts;
gettime(&ts);
- g_rings.insertResponse(ts, client, qname, qtype, static_cast<unsigned int>(udiff), size, cleartextDH, backend, protocol);
+ g_rings.insertResponse(ts, client, qname, qtype, static_cast<unsigned int>(udiff), size, cleartextDH, backend, outgoingProtocol);
switch (cleartextDH.rcode) {
case RCode::NXDomain:
++g_stats.frontendNoError;
break;
}
+
+ doLatencyStats(incomingProtocol, udiff);
}
// listens on a dedicated socket, lobs answers from downstream servers to original requestors
handleResponseSent(*ids, udiff, *dr.remote, dss->d_config.remote, static_cast<unsigned int>(got), cleartextDH, dss->getProtocol());
dss->releaseState(queryId);
-
- doLatencyStats(udiff);
}
}
catch (const std::exception& e){
break;
}
- doLatencyStats(0); // we're not going to measure this
+ doLatencyStats(cs.getProtocol(), 0); // we're not going to measure this
return true;
}
vinfolog("Got answer from %s, relayed to %s (UDP), took %f usec", d_ds->d_config.remote.toStringWithPort(), ids.origRemote.toStringWithPort(), udiff);
handleResponseSent(ids, udiff, *dr.remote, d_ds->d_config.remote, response.d_buffer.size(), cleartextDH, d_ds->getProtocol());
-
- doLatencyStats(udiff);
}
void handleXFRResponse(const struct timeval& now, TCPResponse&& response) override
/* we use dest, always, because we don't want to use the listening address to send a response since it could be 0.0.0.0 */
sendUDPResponse(cs.udpFD, query, dq.delayMsec, dest, remote);
- handleResponseSent(qname, qtype, 0., remote, ComboAddress(), query.size(), *dh, dnsdist::Protocol::DoUDP);
+ handleResponseSent(qname, qtype, 0., remote, ComboAddress(), query.size(), *dh, dnsdist::Protocol::DoUDP, dnsdist::Protocol::DoUDP);
return;
}
stat_t tcpCrossProtocolQueryPipeFull{0};
stat_t tcpCrossProtocolResponsePipeFull{0};
double latencyAvg100{0}, latencyAvg1000{0}, latencyAvg10000{0}, latencyAvg1000000{0};
+ double latencyTCPAvg100{0}, latencyTCPAvg1000{0}, latencyTCPAvg10000{0}, latencyTCPAvg1000000{0};
+ double latencyDoTAvg100{0}, latencyDoTAvg1000{0}, latencyDoTAvg10000{0}, latencyDoTAvg1000000{0};
+ double latencyDoHAvg100{0}, latencyDoHAvg1000{0}, latencyDoHAvg10000{0}, latencyDoHAvg1000000{0};
typedef std::function<uint64_t(const std::string&)> statfunction_t;
typedef boost::variant<stat_t*, pdns::stat_t_trait<double>*, double*, statfunction_t> entry_t;
{"latency-avg1000", &latencyAvg1000},
{"latency-avg10000", &latencyAvg10000},
{"latency-avg1000000", &latencyAvg1000000},
+ {"latency-tcp-avg100", &latencyTCPAvg100},
+ {"latency-tcp-avg1000", &latencyTCPAvg1000},
+ {"latency-tcp-avg10000", &latencyTCPAvg10000},
+ {"latency-tcp-avg1000000", &latencyTCPAvg1000000},
+ {"latency-dot-avg100", &latencyDoTAvg100},
+ {"latency-dot-avg1000", &latencyDoTAvg1000},
+ {"latency-dot-avg10000", &latencyDoTAvg10000},
+ {"latency-dot-avg1000000", &latencyDoTAvg1000000},
+ {"latency-doh-avg100", &latencyDoHAvg100},
+ {"latency-doh-avg1000", &latencyDoHAvg1000},
+ {"latency-doh-avg10000", &latencyDoHAvg10000},
+ {"latency-doh-avg1000000", &latencyDoHAvg1000000},
{"uptime", uptimeOfProcess},
{"real-memory-usage", getRealMemoryUsage},
{"special-memory-usage", getSpecialMemoryUsage},
};
extern struct DNSDistStats g_stats;
-void doLatencyStats(double udiff);
+void doLatencyStats(dnsdist::Protocol protocol, double udiff);
#include "dnsdist-idstate.hh"
return tlsFrontend != nullptr || (dohFrontend != nullptr && dohFrontend->isHTTPS());
}
+ dnsdist::Protocol getProtocol() const
+ {
+ if (dnscryptCtx) {
+ if (udpFD != -1) {
+ return dnsdist::Protocol::DNSCryptUDP;
+ }
+ return dnsdist::Protocol::DNSCryptTCP;
+ }
+ if (isDoH()) {
+ return dnsdist::Protocol::DoH;
+ }
+ else if (hasTLS()) {
+ return dnsdist::Protocol::DoT;
+ }
+ else if (udpFD != -1) {
+ return dnsdist::Protocol::DoUDP;
+ }
+ else {
+ return dnsdist::Protocol::DoTCP;
+ }
+ }
+
std::string getType() const
{
std::string result = udpFD != -1 ? "UDP" : "TCP";
void setIDStateFromDNSQuestion(IDState& ids, DNSQuestion& dq, DNSName&& qname);
ssize_t udpClientSendRequestToBackend(const std::shared_ptr<DownstreamState>& ss, const int sd, const PacketBuffer& request, bool healthCheck = false);
-void handleResponseSent(const DNSName& qname, const QType& qtype, double udiff, const ComboAddress& client, const ComboAddress& backend, unsigned int size, const dnsheader& cleartextDH, dnsdist::Protocol protocol);
-void handleResponseSent(const IDState& ids, double udiff, const ComboAddress& client, const ComboAddress& backend, unsigned int size, const dnsheader& cleartextDH, dnsdist::Protocol protocol);
-
+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);
+void handleResponseSent(const IDState& ids, double udiff, const ComboAddress& client, const ComboAddress& backend, unsigned int size, const dnsheader& cleartextDH, dnsdist::Protocol outgoingProtocol);
if (du->response.size() >= sizeof(dnsheader) && du->contentType.empty()) {
auto dh = reinterpret_cast<const struct dnsheader*>(du->response.data());
- handleResponseSent(qname, QType(qtype), 0., du->ids.origDest, ComboAddress(), du->response.size(), *dh, dnsdist::Protocol::DoH);
+ handleResponseSent(qname, QType(qtype), 0., du->ids.origDest, ComboAddress(), du->response.size(), *dh, dnsdist::Protocol::DoH, dnsdist::Protocol::DoH);
}
sendDoHUnitToTheMainThread(std::move(du), "DoH self-answered response");
return;
'downstream-send-errors', 'trunc-failures', 'no-policy', 'latency0-1',
'latency1-10', 'latency10-50', 'latency50-100', 'latency100-1000',
'latency-slow', 'latency-sum', 'latency-count', 'latency-avg100', 'latency-avg1000',
- 'latency-avg10000', 'latency-avg1000000', 'uptime', 'real-memory-usage', 'noncompliant-queries',
+ 'latency-avg10000', 'latency-avg1000000', 'latency-tcp-avg100', 'latency-tcp-avg1000',
+ 'latency-tcp-avg10000', 'latency-tcp-avg1000000', 'latency-dot-avg100', 'latency-dot-avg1000',
+ 'latency-dot-avg10000', 'latency-dot-avg1000000', 'latency-doh-avg100', 'latency-doh-avg1000',
+ 'latency-doh-avg10000', 'latency-doh-avg1000000', 'uptime', 'real-memory-usage', 'noncompliant-queries',
'noncompliant-responses', 'rdqueries', 'empty-queries', 'cache-hits',
'cache-misses', 'cpu-iowait', 'cpu-steal', 'cpu-sys-msec', 'cpu-user-msec', 'fd-usage', 'dyn-blocked',
'dyn-block-nmg-size', 'rule-servfail', 'rule-truncated', 'security-status',