summaryrefslogtreecommitdiffstats
path: root/dnsdist-web.cc
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-13 21:14:49 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-13 21:14:49 +0000
commit2f230033794fafdf10822568e763d4db68cf6c6b (patch)
tree39ca5c2325b7b43c9a28ca6d4ad4026a61e7eb97 /dnsdist-web.cc
parentAdding debian version 1.8.3-3. (diff)
downloaddnsdist-2f230033794fafdf10822568e763d4db68cf6c6b.tar.xz
dnsdist-2f230033794fafdf10822568e763d4db68cf6c6b.zip
Merging upstream version 1.9.3.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'dnsdist-web.cc')
-rw-r--r--dnsdist-web.cc229
1 files changed, 175 insertions, 54 deletions
diff --git a/dnsdist-web.cc b/dnsdist-web.cc
index 16e1164..066b5c1 100644
--- a/dnsdist-web.cc
+++ b/dnsdist-web.cc
@@ -34,7 +34,9 @@
#include "dnsdist.hh"
#include "dnsdist-dynblocks.hh"
#include "dnsdist-healthchecks.hh"
+#include "dnsdist-metrics.hh"
#include "dnsdist-prometheus.hh"
+#include "dnsdist-rings.hh"
#include "dnsdist-web.hh"
#include "dolog.hh"
#include "gettime.hh"
@@ -175,6 +177,10 @@ std::map<std::string, MetricDefinition> MetricDefinitionStorage::metrics{
{ "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")},
+ { "latency-doq-avg100", MetricDefinition(PrometheusMetricType::gauge, "Average response latency, in microseconds, of the last 100 packets received over DoQ")},
+ { "latency-doq-avg1000", MetricDefinition(PrometheusMetricType::gauge, "Average response latency, in microseconds, of the last 1000 packets received over DoQ")},
+ { "latency-doq-avg10000", MetricDefinition(PrometheusMetricType::gauge, "Average response latency, in microseconds, of the last 10000 packets received over DoQ")},
+ { "latency-doq-avg1000000", MetricDefinition(PrometheusMetricType::gauge, "Average response latency, in microseconds, of the last 1000000 packets received over DoQ")},
{ "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")},
@@ -212,9 +218,9 @@ std::map<std::string, MetricDefinition> MetricDefinitionStorage::metrics{
};
#endif /* DISABLE_PROMETHEUS */
-bool addMetricDefinition(const std::string& name, const std::string& type, const std::string& description, const std::string& customName) {
+bool addMetricDefinition(const dnsdist::prometheus::PrometheusMetricDefinition& def) {
#ifndef DISABLE_PROMETHEUS
- return MetricDefinitionStorage::addMetricDefinition(name, type, description, customName);
+ return MetricDefinitionStorage::addMetricDefinition(def);
#else
return true;
#endif /* DISABLE_PROMETHEUS */
@@ -224,7 +230,7 @@ bool addMetricDefinition(const std::string& name, const std::string& type, const
static bool apiWriteConfigFile(const string& filebasename, const string& content)
{
if (!g_apiReadWrite) {
- errlog("Not writing content to %s since the API is read-only", filebasename);
+ warnlog("Not writing content to %s since the API is read-only", filebasename);
return false;
}
@@ -247,15 +253,14 @@ static bool apiWriteConfigFile(const string& filebasename, const string& content
static void apiSaveACL(const NetmaskGroup& nmg)
{
- vector<string> vec;
- nmg.toStringVector(&vec);
+ auto aclEntries = nmg.toStringVector();
string acl;
- for(const auto& s : vec) {
+ for (const auto& entry : aclEntries) {
if (!acl.empty()) {
acl += ", ";
}
- acl += "\"" + s + "\"";
+ acl += "\"" + entry + "\"";
}
string content = "setACL({" + acl + "})";
@@ -468,7 +473,7 @@ static void handlePrometheus(const YaHTTP::Request& req, YaHTTP::Response& resp)
std::ostringstream output;
static const std::set<std::string> metricBlacklist = { "special-memory-usage", "latency-count", "latency-sum" };
{
- auto entries = g_stats.entries.read_lock();
+ auto entries = dnsdist::metrics::g_stats.entries.read_lock();
for (const auto& entry : *entries) {
const auto& metricName = entry.d_name;
@@ -504,16 +509,16 @@ static void handlePrometheus(const YaHTTP::Request& req, YaHTTP::Response& resp)
output << "# TYPE " << helpName << " " << prometheusTypeName << "\n";
output << prometheusMetricName << " ";
- if (const auto& val = boost::get<pdns::stat_t*>(&entry.d_value)) {
+ if (const auto& val = std::get_if<pdns::stat_t*>(&entry.d_value)) {
output << (*val)->load();
}
- else if (const auto& adval = boost::get<pdns::stat_t_trait<double>*>(&entry.d_value)) {
+ else if (const auto& adval = std::get_if<pdns::stat_t_trait<double>*>(&entry.d_value)) {
output << (*adval)->load();
}
- else if (const auto& dval = boost::get<double*>(&entry.d_value)) {
+ else if (const auto& dval = std::get_if<double*>(&entry.d_value)) {
output << **dval;
}
- else if (const auto& func = boost::get<DNSDistStats::statfunction_t>(&entry.d_value)) {
+ else if (const auto& func = std::get_if<dnsdist::metrics::Stats::statfunction_t>(&entry.d_value)) {
output << (*func)(entry.d_name);
}
@@ -524,20 +529,20 @@ static void handlePrometheus(const YaHTTP::Request& req, YaHTTP::Response& resp)
// Latency histogram buckets
output << "# HELP dnsdist_latency Histogram of responses by latency (in milliseconds)\n";
output << "# TYPE dnsdist_latency histogram\n";
- uint64_t latency_amounts = g_stats.latency0_1;
+ uint64_t latency_amounts = dnsdist::metrics::g_stats.latency0_1;
output << "dnsdist_latency_bucket{le=\"1\"} " << latency_amounts << "\n";
- latency_amounts += g_stats.latency1_10;
+ latency_amounts += dnsdist::metrics::g_stats.latency1_10;
output << "dnsdist_latency_bucket{le=\"10\"} " << latency_amounts << "\n";
- latency_amounts += g_stats.latency10_50;
+ latency_amounts += dnsdist::metrics::g_stats.latency10_50;
output << "dnsdist_latency_bucket{le=\"50\"} " << latency_amounts << "\n";
- latency_amounts += g_stats.latency50_100;
+ latency_amounts += dnsdist::metrics::g_stats.latency50_100;
output << "dnsdist_latency_bucket{le=\"100\"} " << latency_amounts << "\n";
- latency_amounts += g_stats.latency100_1000;
+ latency_amounts += dnsdist::metrics::g_stats.latency100_1000;
output << "dnsdist_latency_bucket{le=\"1000\"} " << latency_amounts << "\n";
- latency_amounts += g_stats.latencySlow; // Should be the same as latency_count
+ latency_amounts += dnsdist::metrics::g_stats.latencySlow; // Should be the same as latency_count
output << "dnsdist_latency_bucket{le=\"+Inf\"} " << latency_amounts << "\n";
- output << "dnsdist_latency_sum " << g_stats.latencySum << "\n";
- output << "dnsdist_latency_count " << g_stats.latencyCount << "\n";
+ output << "dnsdist_latency_sum " << dnsdist::metrics::g_stats.latencySum << "\n";
+ output << "dnsdist_latency_count " << dnsdist::metrics::g_stats.latencyCount << "\n";
auto states = g_dstates.getLocal();
const string statesbase = "dnsdist_server_";
@@ -592,6 +597,18 @@ static void handlePrometheus(const YaHTTP::Request& req, YaHTTP::Response& resp)
output << "# TYPE " << statesbase << "tlsresumptions " << "counter" << "\n";
output << "# HELP " << statesbase << "tcplatency " << "Server's latency when answering TCP questions in milliseconds" << "\n";
output << "# TYPE " << statesbase << "tcplatency " << "gauge" << "\n";
+ output << "# HELP " << statesbase << "healthcheckfailures " << "Number of health check attempts that failed (total)" << "\n";
+ output << "# TYPE " << statesbase << "healthcheckfailures " << "counter" << "\n";
+ output << "# HELP " << statesbase << "healthcheckfailuresparsing " << "Number of health check attempts where the response could not be parsed" << "\n";
+ output << "# TYPE " << statesbase << "healthcheckfailuresparsing " << "counter" << "\n";
+ output << "# HELP " << statesbase << "healthcheckfailurestimeout " << "Number of health check attempts where the response did not arrive in time" << "\n";
+ output << "# TYPE " << statesbase << "healthcheckfailurestimeout " << "counter" << "\n";
+ output << "# HELP " << statesbase << "healthcheckfailuresnetwork " << "Number of health check attempts that experienced a network issue" << "\n";
+ output << "# TYPE " << statesbase << "healthcheckfailuresnetwork " << "counter" << "\n";
+ output << "# HELP " << statesbase << "healthcheckfailuresmismatch " << "Number of health check attempts where the response did not match the query" << "\n";
+ output << "# TYPE " << statesbase << "healthcheckfailuresmismatch " << "counter" << "\n";
+ output << "# HELP " << statesbase << "healthcheckfailuresinvalid " << "Number of health check attempts where the DNS response was invalid" << "\n";
+ output << "# TYPE " << statesbase << "healthcheckfailuresinvalid " << "counter" << "\n";
for (const auto& state : *states) {
string serverName;
@@ -635,6 +652,12 @@ static void handlePrometheus(const YaHTTP::Request& req, YaHTTP::Response& resp)
output << statesbase << "tcpavgqueriesperconn" << label << " " << state->tcpAvgQueriesPerConnection << "\n";
output << statesbase << "tcpavgconnduration" << label << " " << state->tcpAvgConnectionDuration << "\n";
output << statesbase << "tlsresumptions" << label << " " << state->tlsResumptions << "\n";
+ output << statesbase << "healthcheckfailures" << label << " " << state->d_healthCheckMetrics.d_failures << "\n";
+ output << statesbase << "healthcheckfailuresparsing" << label << " " << state->d_healthCheckMetrics.d_parseErrors << "\n";
+ output << statesbase << "healthcheckfailurestimeout" << label << " " << state->d_healthCheckMetrics.d_timeOuts << "\n";
+ output << statesbase << "healthcheckfailuresnetwork" << label << " " << state->d_healthCheckMetrics.d_networkErrors << "\n";
+ output << statesbase << "healthcheckfailuresmismatch" << label << " " << state->d_healthCheckMetrics.d_mismatchErrors << "\n";
+ output << statesbase << "healthcheckfailuresinvalid" << label << " " << state->d_healthCheckMetrics.d_invalidResponseErrors << "\n";
}
const string frontsbase = "dnsdist_frontend_";
@@ -650,8 +673,8 @@ static void handlePrometheus(const YaHTTP::Request& req, YaHTTP::Response& resp)
output << "# TYPE " << frontsbase << "tcpdiedsendingresponse " << "counter" << "\n";
output << "# HELP " << frontsbase << "tcpgaveup " << "Amount of TCP connections terminated after too many attempts to get a connection to the backend" << "\n";
output << "# TYPE " << frontsbase << "tcpgaveup " << "counter" << "\n";
- output << "# HELP " << frontsbase << "tcpclientimeouts " << "Amount of TCP connections terminated by a timeout while reading from the client" << "\n";
- output << "# TYPE " << frontsbase << "tcpclientimeouts " << "counter" << "\n";
+ output << "# HELP " << frontsbase << "tcpclienttimeouts " << "Amount of TCP connections terminated by a timeout while reading from the client" << "\n";
+ output << "# TYPE " << frontsbase << "tcpclienttimeouts " << "counter" << "\n";
output << "# HELP " << frontsbase << "tcpdownstreamtimeouts " << "Amount of TCP connections terminated by a timeout while reading from the backend" << "\n";
output << "# TYPE " << frontsbase << "tcpdownstreamtimeouts " << "counter" << "\n";
output << "# HELP " << frontsbase << "tcpcurrentconnections " << "Amount of current incoming TCP connections from clients" << "\n";
@@ -672,7 +695,6 @@ static void handlePrometheus(const YaHTTP::Request& req, YaHTTP::Response& resp)
output << "# TYPE " << frontsbase << "tlsunknownticketkeys " << "counter" << "\n";
output << "# HELP " << frontsbase << "tlsinactiveticketkeys " << "Amount of TLS sessions resumed from an inactive key" << "\n";
output << "# TYPE " << frontsbase << "tlsinactiveticketkeys " << "counter" << "\n";
-
output << "# HELP " << frontsbase << "tlshandshakefailures " << "Amount of TLS handshake failures" << "\n";
output << "# TYPE " << frontsbase << "tlshandshakefailures " << "counter" << "\n";
@@ -700,7 +722,7 @@ static void handlePrometheus(const YaHTTP::Request& req, YaHTTP::Response& resp)
output << frontsbase << "tcpdiedreadingquery" << label << front->tcpDiedReadingQuery.load() << "\n";
output << frontsbase << "tcpdiedsendingresponse" << label << front->tcpDiedSendingResponse.load() << "\n";
output << frontsbase << "tcpgaveup" << label << front->tcpGaveUp.load() << "\n";
- output << frontsbase << "tcpclientimeouts" << label << front->tcpClientTimeouts.load() << "\n";
+ output << frontsbase << "tcpclienttimeouts" << label << front->tcpClientTimeouts.load() << "\n";
output << frontsbase << "tcpdownstreamtimeouts" << label << front->tcpDownstreamTimeouts.load() << "\n";
output << frontsbase << "tcpcurrentconnections" << label << front->tcpCurrentConnections.load() << "\n";
output << frontsbase << "tcpmaxconcurrentconnections" << label << front->tcpMaxConcurrentConnections.load() << "\n";
@@ -723,7 +745,7 @@ static void handlePrometheus(const YaHTTP::Request& req, YaHTTP::Response& resp)
errorCounters = &front->tlsFrontend->d_tlsCounters;
}
else if (front->dohFrontend != nullptr) {
- errorCounters = &front->dohFrontend->d_tlsCounters;
+ errorCounters = &front->dohFrontend->d_tlsContext.d_tlsCounters;
}
if (errorCounters != nullptr) {
@@ -761,7 +783,7 @@ static void handlePrometheus(const YaHTTP::Request& req, YaHTTP::Response& resp)
#ifdef HAVE_DNS_OVER_HTTPS
std::map<std::string,uint64_t> dohFrontendDuplicates;
for(const auto& doh : g_dohlocals) {
- const string frontName = doh->d_local.toStringWithPort();
+ const string frontName = doh->d_tlsContext.d_addr.toStringWithPort();
uint64_t threadNumber = 0;
auto dupPair = frontendDuplicates.emplace(frontName, 1);
if (!dupPair.second) {
@@ -895,18 +917,18 @@ using namespace json11;
static void addStatsToJSONObject(Json::object& obj)
{
- auto entries = g_stats.entries.read_lock();
+ auto entries = dnsdist::metrics::g_stats.entries.read_lock();
for (const auto& entry : *entries) {
if (entry.d_name == "special-memory-usage") {
continue; // Too expensive for get-all
}
- if (const auto& val = boost::get<pdns::stat_t*>(&entry.d_value)) {
+ if (const auto& val = std::get_if<pdns::stat_t*>(&entry.d_value)) {
obj.emplace(entry.d_name, (double)(*val)->load());
- } else if (const auto& adval = boost::get<pdns::stat_t_trait<double>*>(&entry.d_value)) {
+ } else if (const auto& adval = std::get_if<pdns::stat_t_trait<double>*>(&entry.d_value)) {
obj.emplace(entry.d_name, (*adval)->load());
- } else if (const auto& dval = boost::get<double*>(&entry.d_value)) {
+ } else if (const auto& dval = std::get_if<double*>(&entry.d_value)) {
obj.emplace(entry.d_name, (**dval));
- } else if (const auto& func = boost::get<DNSDistStats::statfunction_t>(&entry.d_value)) {
+ } else if (const auto& func = std::get_if<dnsdist::metrics::Stats::statfunction_t>(&entry.d_value)) {
obj.emplace(entry.d_name, (double)(*func)(entry.d_name));
}
}
@@ -1084,6 +1106,12 @@ static void addServerToJSON(Json::array& servers, int id, const std::shared_ptr<
{"tcpAvgConnectionDuration", (double)a->tcpAvgConnectionDuration},
{"tlsResumptions", (double)a->tlsResumptions},
{"tcpLatency", (double)(a->latencyUsecTCP/1000.0)},
+ {"healthCheckFailures", (double)(a->d_healthCheckMetrics.d_failures)},
+ {"healthCheckFailuresParsing", (double)(a->d_healthCheckMetrics.d_parseErrors)},
+ {"healthCheckFailuresTimeout", (double)(a->d_healthCheckMetrics.d_timeOuts)},
+ {"healthCheckFailuresNetwork", (double)(a->d_healthCheckMetrics.d_networkErrors)},
+ {"healthCheckFailuresMismatch", (double)(a->d_healthCheckMetrics.d_mismatchErrors)},
+ {"healthCheckFailuresInvalid", (double)(a->d_healthCheckMetrics.d_invalidResponseErrors)},
{"dropRate", (double)a->dropRate}
};
@@ -1151,7 +1179,7 @@ static void handleStats(const YaHTTP::Request& req, YaHTTP::Response& resp)
errorCounters = &front->tlsFrontend->d_tlsCounters;
}
else if (front->dohFrontend != nullptr) {
- errorCounters = &front->dohFrontend->d_tlsCounters;
+ errorCounters = &front->dohFrontend->d_tlsContext.d_tlsCounters;
}
if (errorCounters != nullptr) {
frontend["tlsHandshakeFailuresDHKeyTooSmall"] = (double)errorCounters->d_dhKeyTooSmall;
@@ -1174,7 +1202,7 @@ static void handleStats(const YaHTTP::Request& req, YaHTTP::Response& resp)
for (const auto& doh : g_dohlocals) {
dohs.emplace_back(Json::object{
{ "id", num++ },
- { "address", doh->d_local.toStringWithPort() },
+ { "address", doh->d_tlsContext.d_addr.toStringWithPort() },
{ "http-connects", (double) doh->d_httpconnects },
{ "http1-queries", (double) doh->d_http1Stats.d_nbQueries },
{ "http2-queries", (double) doh->d_http2Stats.d_nbQueries },
@@ -1239,6 +1267,7 @@ static void handleStats(const YaHTTP::Request& req, YaHTTP::Response& resp)
{"id", num++},
{"creationOrder", (double)a.d_creationOrder},
{"uuid", boost::uuids::to_string(a.d_id)},
+ {"name", a.d_name},
{"matches", (double)a.d_rule->d_matches},
{"rule", a.d_rule->toString()},
{"action", a.d_action->toString()},
@@ -1254,14 +1283,13 @@ static void handleStats(const YaHTTP::Request& req, YaHTTP::Response& resp)
string acl;
{
- vector<string> vec;
- g_ACL.getLocal()->toStringVector(&vec);
+ auto aclEntries = g_ACL.getLocal()->toStringVector();
- for (const auto& s : vec) {
+ for (const auto& entry : aclEntries) {
if (!acl.empty()) {
acl += ", ";
}
- acl += s;
+ acl += entry;
}
}
@@ -1362,34 +1390,34 @@ static void handleStatsOnly(const YaHTTP::Request& req, YaHTTP::Response& resp)
Json::array doc;
{
- auto entries = g_stats.entries.read_lock();
+ auto entries = dnsdist::metrics::g_stats.entries.read_lock();
for (const auto& item : *entries) {
if (item.d_name == "special-memory-usage") {
continue; // Too expensive for get-all
}
- if (const auto& val = boost::get<pdns::stat_t*>(&item.d_value)) {
+ if (const auto& val = std::get_if<pdns::stat_t*>(&item.d_value)) {
doc.push_back(Json::object {
{ "type", "StatisticItem" },
{ "name", item.d_name },
{ "value", (double)(*val)->load() }
});
}
- else if (const auto& adval = boost::get<pdns::stat_t_trait<double>*>(&item.d_value)) {
+ else if (const auto& adval = std::get_if<pdns::stat_t_trait<double>*>(&item.d_value)) {
doc.push_back(Json::object {
{ "type", "StatisticItem" },
{ "name", item.d_name },
{ "value", (*adval)->load() }
});
}
- else if (const auto& dval = boost::get<double*>(&item.d_value)) {
+ else if (const auto& dval = std::get_if<double*>(&item.d_value)) {
doc.push_back(Json::object {
{ "type", "StatisticItem" },
{ "name", item.d_name },
{ "value", (**dval) }
});
}
- else if (const auto& func = boost::get<DNSDistStats::statfunction_t>(&item.d_value)) {
+ else if (const auto& func = std::get_if<dnsdist::metrics::Stats::statfunction_t>(&item.d_value)) {
doc.push_back(Json::object {
{ "type", "StatisticItem" },
{ "name", item.d_name },
@@ -1496,18 +1524,12 @@ static void handleAllowFrom(const YaHTTP::Request& req, YaHTTP::Response& resp)
}
}
if (resp.status == 200) {
- Json::array acl;
- vector<string> vec;
- g_ACL.getLocal()->toStringVector(&vec);
-
- for(const auto& s : vec) {
- acl.push_back(s);
- }
+ auto aclEntries = g_ACL.getLocal()->toStringVector();
Json::object obj{
{ "type", "ConfigSetting" },
{ "name", "allow-from" },
- { "value", acl }
+ { "value", aclEntries }
};
Json my_json = obj;
resp.body = my_json.dump();
@@ -1600,13 +1622,111 @@ static void handleCacheManagement(const YaHTTP::Request& req, YaHTTP::Response&
}
#endif /* DISABLE_WEB_CACHE_MANAGEMENT */
+template<typename T> static void addRingEntryToList(const struct timespec& now, Json::array& list, const T& entry)
+{
+ constexpr bool response = std::is_same_v<T, Rings::Response>;
+ Json::object tmp{
+ { "age", static_cast<double>(DiffTime(entry.when, now)) },
+ { "id", ntohs(entry.dh.id) },
+ { "name", entry.name.toString() },
+ { "requestor", entry.requestor.toStringWithPort() },
+ { "size", static_cast<int>(entry.size) },
+ { "qtype", entry.qtype },
+ { "protocol", entry.protocol.toString() },
+ { "rd", static_cast<bool>(entry.dh.rd) },
+ };
+ if constexpr (!response) {
+#if defined(DNSDIST_RINGS_WITH_MACADDRESS)
+ tmp.emplace("mac", entry.hasmac ? std::string(reinterpret_cast<const char*>(entry.macaddress.data()), entry.macaddress.size()) : std::string());
+#endif
+ }
+ else {
+ tmp.emplace("latency", static_cast<double>(entry.usec));
+ tmp.emplace("rcode", static_cast<uint8_t>(entry.dh.rcode));
+ tmp.emplace("tc", static_cast<bool>(entry.dh.tc));
+ tmp.emplace("aa", static_cast<bool>(entry.dh.aa));
+ tmp.emplace("answers", ntohs(entry.dh.ancount));
+ auto server = entry.ds.toStringWithPort();
+ tmp.emplace("backend", server != "0.0.0.0:0" ? std::move(server) : "Cache");
+ }
+ list.push_back(std::move(tmp));
+}
+
+static void handleRings(const YaHTTP::Request& req, YaHTTP::Response& resp)
+{
+ handleCORS(req, resp);
+
+ std::optional<size_t> maxNumberOfQueries{std::nullopt};
+ std::optional<size_t> maxNumberOfResponses{std::nullopt};
+
+ const auto maxQueries = req.getvars.find("maxQueries");
+ if (maxQueries != req.getvars.end()) {
+ try {
+ maxNumberOfQueries = pdns::checked_stoi<size_t>(maxQueries->second);
+ }
+ catch (const std::exception& exp) {
+ vinfolog("Error parsing the 'maxQueries' value from rings HTTP GET query: %s", exp.what());
+ }
+ }
+
+ const auto maxResponses = req.getvars.find("maxResponses");
+ if (maxResponses != req.getvars.end()) {
+ try {
+ maxNumberOfResponses = pdns::checked_stoi<size_t>(maxResponses->second);
+ }
+ catch (const std::exception& exp) {
+ vinfolog("Error parsing the 'maxResponses' value from rings HTTP GET query: %s", exp.what());
+ }
+ }
+
+ resp.status = 200;
+
+ Json::object doc;
+ size_t numberOfQueries = 0;
+ size_t numberOfResponses = 0;
+ Json::array queries;
+ Json::array responses;
+ struct timespec now
+ {
+ };
+ gettime(&now);
+
+ for (const auto& shard : g_rings.d_shards) {
+ if (!maxNumberOfQueries || numberOfQueries < *maxNumberOfQueries) {
+ auto queryRing = shard->queryRing.lock();
+ for (const auto& entry : *queryRing) {
+ addRingEntryToList(now, queries, entry);
+ numberOfQueries++;
+ if (maxNumberOfQueries && numberOfQueries >= *maxNumberOfQueries) {
+ break;
+ }
+ }
+ }
+ if (!maxNumberOfResponses || numberOfResponses < *maxNumberOfResponses) {
+ auto responseRing = shard->respRing.lock();
+ for (const auto& entry : *responseRing) {
+ addRingEntryToList(now, responses, entry);
+ numberOfResponses++;
+ if (maxNumberOfResponses && numberOfResponses >= *maxNumberOfResponses) {
+ break;
+ }
+ }
+ }
+ }
+ doc.emplace("queries", std::move(queries));
+ doc.emplace("responses", std::move(responses));
+ Json my_json = doc;
+ resp.body = my_json.dump();
+ resp.headers["Content-Type"] = "application/json";
+}
+
static std::unordered_map<std::string, std::function<void(const YaHTTP::Request&, YaHTTP::Response&)>> s_webHandlers;
void registerWebHandler(const std::string& endpoint, std::function<void(const YaHTTP::Request&, YaHTTP::Response&)> handler);
void registerWebHandler(const std::string& endpoint, std::function<void(const YaHTTP::Request&, YaHTTP::Response&)> handler)
{
- s_webHandlers[endpoint] = handler;
+ s_webHandlers[endpoint] = std::move(handler);
}
void clearWebHandlers()
@@ -1664,6 +1784,7 @@ void registerBuiltInWebHandlers()
registerWebHandler("/api/v1/servers/localhost", handleStats);
registerWebHandler("/api/v1/servers/localhost/pool", handlePoolStats);
registerWebHandler("/api/v1/servers/localhost/statistics", handleStatsOnly);
+ registerWebHandler("/api/v1/servers/localhost/rings", handleRings);
#ifndef DISABLE_WEB_CONFIG
registerWebHandler("/api/v1/servers/localhost/config", handleConfigDump);
registerWebHandler("/api/v1/servers/localhost/config/allow-from", handleAllowFrom);
@@ -1759,10 +1880,10 @@ static void connectionThread(WebClientConnection&& conn)
vinfolog("Webserver thread died with parse error exception while processing a request from %s: %s", conn.getClient().toStringWithPort(), e.what());
}
catch (const std::exception& e) {
- errlog("Webserver thread died with exception while processing a request from %s: %s", conn.getClient().toStringWithPort(), e.what());
+ vinfolog("Webserver thread died with exception while processing a request from %s: %s", conn.getClient().toStringWithPort(), e.what());
}
catch (...) {
- errlog("Webserver thread died with exception while processing a request from %s", conn.getClient().toStringWithPort());
+ vinfolog("Webserver thread died with exception while processing a request from %s", conn.getClient().toStringWithPort());
}
}
@@ -1845,7 +1966,7 @@ void dnsdistWebserverThread(int sock, const ComboAddress& local)
t.detach();
}
catch (const std::exception& e) {
- errlog("Had an error accepting new webserver connection: %s", e.what());
+ vinfolog("Had an error accepting new webserver connection: %s", e.what());
}
}
}