status = "DOWN";
else
status = (a->upStatus ? "up" : "down");
+
Json::array pools;
for(const auto& p: a->pools)
pools.push_back(p);
{"order", (int)a->order},
{"pools", pools},
{"latency", (int)(a->latencyUsec/1000.0)},
- {"queries", (double)a->queries}};
+ {"queries", (double)a->queries},
+ {"sendErrors", (int)a->sendErrors}
+ };
/* sending a latency for a DOWN server doesn't make sense */
if (a->availability == DownstreamState::Availability::Down) {
frontends.push_back(frontend);
}
+ Json::array pools;
+ auto localPools = g_pools.getCopy();
+ num=0;
+ for(const auto& pool :localPools) {
+ const auto& cache = pool.second->packetCache;
+ Json::object entry {
+ { "id", num++ },
+ { "name", pool.first },
+ { "serversCount", (int) pool.second->servers.size() },
+ { "cacheSize", (double) (cache ? cache->getMaxEntries() : 0) },
+ { "cacheEntries", (double) (cache ? cache->getEntriesCount() : 0) },
+ { "cacheHits", (double) (cache ? cache->getHits() : 0) },
+ { "cacheMisses", (double) (cache ? cache->getMisses() : 0) },
+ { "cacheDeferredInserts", (double) (cache ? cache->getDeferredInserts() : 0) },
+ { "cacheDeferredLookups", (double) (cache ? cache->getDeferredLookups() : 0) },
+ { "cacheLookupCollisions", (double) (cache ? cache->getLookupCollisions() : 0) },
+ { "cacheInsertCollisions", (double) (cache ? cache->getInsertCollisions() : 0) },
+ { "cacheTTLTooShorts", (double) (cache ? cache->getTTLTooShorts() : 0) }
+ };
+ pools.push_back(entry);
+ }
+
Json::array rules;
auto localRules = g_rulactions.getCopy();
num=0;
for(const auto& a : localRules) {
Json::object rule{
- {"id", num++},
- {"matches", (double)a.first->d_matches},
- {"rule", a.first->toString()},
- {"action", a.second->toString()},
- {"action-stats", a.second->getStats()}
+ {"id", num++},
+ {"matches", (double)a.first->d_matches},
+ {"rule", a.first->toString()},
+ {"action", a.second->toString()},
+ {"action-stats", a.second->getStats()}
};
rules.push_back(rule);
}
responseRules.push_back(rule);
}
+ Json::array cacheHitResponseRules;
+ num=0;
+ auto localCacheHitResponseRules = g_cachehitresprulactions.getCopy();
+ for(const auto& a : localCacheHitResponseRules) {
+ Json::object rule{
+ {"id", num++},
+ {"matches", (double)a.first->d_matches},
+ {"rule", a.first->toString()},
+ {"action", a.second->toString()},
+ };
+ cacheHitResponseRules.push_back(rule);
+ }
+
string acl;
vector<string> vec;
for(const auto& s : vec) {
if(!acl.empty()) acl += ", ";
- acl+=s;
+ acl+=s;
}
string localaddresses;
for(const auto& loc : g_locals) {
}
Json my_json = Json::object {
- { "daemon_type", "dnsdist" },
- { "version", VERSION},
- { "servers", servers},
- { "frontends", frontends },
- { "rules", rules},
- { "response-rules", responseRules},
- { "acl", acl},
- { "local", localaddresses}
+ { "daemon_type", "dnsdist" },
+ { "version", VERSION},
+ { "servers", servers},
+ { "frontends", frontends },
+ { "pools", pools },
+ { "rules", rules},
+ { "response-rules", responseRules},
+ { "cache-hit-response-rules", cacheHitResponseRules},
+ { "acl", acl},
+ { "local", localaddresses}
};
resp.headers["Content-Type"] = "application/json";
resp.body=my_json.dump();
Get a quick overview of several parameters.
:>json string acl: A string of comma-separated netmasks currently allowed by the :ref:`ACL <ACL>`.
+ :>json list cache-hit-response-rules: A list of :json:object:`ResponseRule` objects applied on cache hits
:>json string daemon_type: The type of daemon, always "dnsdist"
:>json list frontends: A list of :json:object:`Frontend` objects
+ :>json list pools: A list of :json:object:`Pool` objects
:>json list response-rules: A list of :json:object:`ResponseRule` objects
:>json list rules: A list of :json:object:`Rule` objects
:>json list servers: A list of :json:object:`Server` objects
:property boolean udp: true if this is a UDP bind
:property boolean tcp: true if this is a TCP bind
+.. json:object:: Pool
+
+ A description of a pool of backend servers.
+
+ :property integer id: Internal identifier
+ :property integer cacheDeferredInserts: The number of times an entry could not be inserted in the associated cache, if any, because of a lock
+ :property integer cacheDeferredLookups: The number of times an entry could not be looked up from the associated cache, if any, because of a lock
+ :property integer cacheEntries: The current number of entries in the associated cache, if any
+ :property integer cacheHits: The number of cache hits for the associated cache, if any
+ :property integer cacheLookupCollisions: The number of times an entry retrieved from the cache based on the query hash did not match the actual query
+ :property integer cacheInsertCollisions: The number of times an entry could not be inserted into the cache because a different entry with the same hash already existed
+ :property integer cacheMisses: The number of cache misses for the associated cache, if any
+ :property integer cacheSize: The maximum number of entries in the associated cache, if any
+ :property integer cacheTTLTooShorts: The number of times an entry could not be inserted into the cache because its TTL was set below the minimum threshold
+ :property string name: Name of the pool
+ :property integer serversCount: Number of backends in this pool
+
.. json:object:: Rule
This represents a policy that is applied to queries
:property string action: The action taken when the rule matches (e.g. "to pool abuse")
- :property dict action-stats: TODO
+ :property dict action-stats: A list of statistics whose content varies depending on the kind of rule
:property integer id: The identifier (or order) of this rule
:property integer matches: How many times this rule was hit
:property string rule: The matchers for the packet (e.g. "qname==bad-domain1.example., bad-domain2.example.")
This represents a policy that is applied to responses
- TODO
+ :property string action: The action taken when the rule matches (e.g. "drop")
+ :property integer id: The identifier (or order) of this rule
+ :property integer matches: How many times this rule was hit
+ :property string rule: The matchers for the packet (e.g. "qname==bad-domain1.example., bad-domain2.example.")
.. json:object:: Server
:property integer qps: The current number of queries per second to this server
:property integer qpsLimit: The configured maximum number of queries per second
:property integer queries: Total number of queries sent to this backend
- :property integer reuseds: TODO
+ :property integer reuseds: Number of queries for which a response was not received in time
+ :property integer sendErrors: Number of network errors while sending a query to this server
:property string state: The state of the server (e.g. "DOWN" or "up")
:property integer weight: The weight assigned to this server
self.assertEquals(content['daemon_type'], 'dnsdist')
- for key in ['version', 'acl', 'local', 'rules', 'response-rules', 'servers', 'frontends']:
+ for key in ['version', 'acl', 'local', 'rules', 'response-rules', 'cache-hit-response-rules', 'servers', 'frontends', 'pools']:
self.assertIn(key, content)
for rule in content['rules']:
for key in ['id', 'matches']:
self.assertTrue(rule[key] >= 0)
+ for rule in content['cache-hit-response-rules']:
+ for key in ['id', 'matches', 'rule', 'action']:
+ self.assertIn(key, rule)
+ for key in ['id', 'matches']:
+ self.assertTrue(rule[key] >= 0)
+
for server in content['servers']:
for key in ['id', 'latency', 'name', 'weight', 'outstanding', 'qpsLimit',
- 'reuseds', 'state', 'address', 'pools', 'qps', 'queries', 'order']:
+ 'reuseds', 'state', 'address', 'pools', 'qps', 'queries', 'order', 'sendErrors']:
self.assertIn(key, server)
for key in ['id', 'latency', 'weight', 'outstanding', 'qpsLimit', 'reuseds',
for key in ['id', 'queries']:
self.assertTrue(frontend[key] >= 0)
+ for pool in content['pools']:
+ for key in ['id', 'name', 'cacheSize', 'cacheEntries', 'cacheHits', 'cacheMisses', 'cacheDeferredInserts', 'cacheDeferredLookups', 'cacheLookupCollisions', 'cacheInsertCollisions', 'cacheTTLTooShorts']:
+ self.assertIn(key, pool)
+
+ for key in ['id', 'cacheSize', 'cacheEntries', 'cacheHits', 'cacheMisses', 'cacheDeferredInserts', 'cacheDeferredLookups', 'cacheLookupCollisions', 'cacheInsertCollisions', 'cacheTTLTooShorts']:
+ self.assertTrue(pool[key] >= 0)
+
def testServersIDontExist(self):
"""
API: /api/v1/servers/idontexist (should be 404)