using namespace json11;
+static void addStatsToJSONObject(Json::object& obj)
+{
+ for (const auto& e : g_stats.entries) {
+ if (e.first == "special-memory-usage") {
+ continue; // Too expensive for get-all
+ }
+ if (const auto& val = boost::get<pdns::stat_t*>(&e.second)) {
+ obj.insert({e.first, (double)(*val)->load()});
+ } else if (const auto& adval = boost::get<pdns::stat_t_trait<double>*>(&e.second)) {
+ obj.insert({e.first, (*adval)->load()});
+ } else if (const auto& dval = boost::get<double*>(&e.second)) {
+ obj.insert({e.first, (**dval)});
+ } else {
+ obj.insert({e.first, (double)(*boost::get<DNSDistStats::statfunction_t>(&e.second))(e.first)});
+ }
+ }
+}
+
#ifndef DISABLE_BUILTIN_HTML
static void handleJSONStats(const YaHTTP::Request& req, YaHTTP::Response& resp)
{
{ "server-policy", g_policy.getLocal()->getName()}
};
- for (const auto& e : g_stats.entries) {
- if (e.first == "special-memory-usage")
- continue; // Too expensive for get-all
- if (const auto& val = boost::get<pdns::stat_t*>(&e.second)) {
- obj.insert({e.first, (double)(*val)->load()});
- } else if (const auto& adval = boost::get<pdns::stat_t_trait<double>*>(&e.second)) {
- obj.insert({e.first, (*adval)->load()});
- } else if (const auto& dval = boost::get<double*>(&e.second)) {
- obj.insert({e.first, (**dval)});
- } else {
- obj.insert({e.first, (double)(*boost::get<DNSDistStats::statfunction_t>(&e.second))(e.first)});
- }
- }
+ addStatsToJSONObject(obj);
+
Json my_json = obj;
resp.body = my_json.dump();
resp.headers["Content-Type"] = "application/json";
localaddressesStr += addr;
}
+ Json::object stats;
+ addStatsToJSONObject(stats);
+
Json my_json = Json::object {
{ "daemon_type", "dnsdist" },
{ "version", VERSION},
{ "self-answered-response-rules", selfAnsweredResponseRules},
{ "acl", acl},
{ "local", localaddressesStr},
- { "dohFrontends", dohs }
+ { "dohFrontends", dohs },
+ { "statistics", stats }
};
resp.headers["Content-Type"] = "application/json";
resp.body = my_json.dump();
{ "value", (double)(*val)->load() }
});
}
- else if(const auto& adval = boost::get<pdns::stat_t_trait<double>*>(&item.second)) {
+ else if (const auto& adval = boost::get<pdns::stat_t_trait<double>*>(&item.second)) {
doc.push_back(Json::object {
{ "type", "StatisticItem" },
{ "name", item.first },
webserver("127.0.0.1:%s")
setWebserverConfig({password="%s", apiKey="%s"})
"""
+ _expectedMetrics = ['responses', 'servfail-responses', 'queries', 'acl-drops',
+ 'frontend-noerror', 'frontend-nxdomain', 'frontend-servfail',
+ 'rule-drop', 'rule-nxdomain', 'rule-refused', 'self-answered', 'downstream-timeouts',
+ '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',
+ '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',
+ 'udp-in-csum-errors', 'udp-in-errors', 'udp-noport-errors', 'udp-recvbuf-errors', 'udp-sndbuf-errors',
+ 'udp6-in-errors', 'udp6-recvbuf-errors', 'udp6-sndbuf-errors', 'udp6-noport-errors', 'udp6-in-csum-errors',
+ 'doh-query-pipe-full', 'doh-response-pipe-full', 'proxy-protocol-invalid', 'tcp-listen-overflows',
+ 'outgoing-doh-query-pipe-full', 'tcp-query-pipe-full', 'tcp-cross-protocol-query-pipe-full',
+ 'tcp-cross-protocol-response-pipe-full']
class TestAPIBasics(APITestsBase):
for key in ['id', 'cacheSize', 'cacheEntries', 'cacheHits', 'cacheMisses', 'cacheDeferredInserts', 'cacheDeferredLookups', 'cacheLookupCollisions', 'cacheInsertCollisions', 'cacheTTLTooShorts', 'cacheCleanupCount']:
self.assertTrue(pool[key] >= 0)
+ stats = content['statistics']
+ for key in self._expectedMetrics:
+ self.assertIn(key, stats)
+ self.assertTrue(stats[key] >= 0)
+ for key in stats:
+ self.assertIn(key, self._expectedMetrics)
+
def testServersLocalhostPool(self):
"""
API: /api/v1/servers/localhost/pool?name=mypool
self.assertEqual(entry['type'], 'StatisticItem')
values[entry['name']] = entry['value']
- expected = ['responses', 'servfail-responses', 'queries', 'acl-drops',
- 'frontend-noerror', 'frontend-nxdomain', 'frontend-servfail',
- 'rule-drop', 'rule-nxdomain', 'rule-refused', 'self-answered', 'downstream-timeouts',
- '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',
- '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',
- 'udp-in-csum-errors', 'udp-in-errors', 'udp-noport-errors', 'udp-recvbuf-errors', 'udp-sndbuf-errors',
- 'udp6-in-errors', 'udp6-recvbuf-errors', 'udp6-sndbuf-errors', 'udp6-noport-errors', 'udp6-in-csum-errors',
- 'doh-query-pipe-full', 'doh-response-pipe-full', 'proxy-protocol-invalid', 'tcp-listen-overflows',
- 'outgoing-doh-query-pipe-full', 'tcp-query-pipe-full', 'tcp-cross-protocol-query-pipe-full',
- 'tcp-cross-protocol-response-pipe-full']
-
- for key in expected:
+ for key in self._expectedMetrics:
self.assertIn(key, values)
self.assertTrue(values[key] >= 0)
for key in values:
- self.assertIn(key, expected)
+ self.assertIn(key, self._expectedMetrics)
def testJsonstatStats(self):
"""
self.assertTrue(r.json())
content = r.json()
- expected = ['responses', 'servfail-responses', 'queries', 'acl-drops',
- 'frontend-noerror', 'frontend-nxdomain', 'frontend-servfail',
- 'rule-drop', 'rule-nxdomain', 'rule-refused', 'rule-truncated', 'self-answered', 'downstream-timeouts',
- 'downstream-send-errors', 'trunc-failures', 'no-policy', 'latency0-1',
- 'latency1-10', 'latency10-50', 'latency50-100', 'latency100-1000',
- 'latency-slow', 'latency-avg100', 'latency-avg1000', 'latency-avg10000',
- 'latency-avg1000000', 'uptime', 'real-memory-usage', 'noncompliant-queries',
- 'noncompliant-responses', 'rdqueries', 'empty-queries', 'cache-hits',
- 'cache-misses', 'cpu-user-msec', 'cpu-sys-msec', 'fd-usage', 'dyn-blocked',
- 'dyn-block-nmg-size', 'packetcache-hits', 'packetcache-misses', 'over-capacity-drops',
- 'too-old-drops', 'proxy-protocol-invalid', 'doh-query-pipe-full', 'doh-response-pipe-full']
-
- for key in expected:
+ for key in self._expectedMetrics:
self.assertIn(key, content)
self.assertTrue(content[key] >= 0)