From: Thomas du Boÿs Date: Fri, 11 Jan 2019 10:02:15 +0000 (+0100) Subject: Add Rcode response statistics on API X-Git-Tag: auth-4.2.0-beta1~5^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=87798d5e536b67df3a466eeec4c3f3b286c1d319;p=thirdparty%2Fpdns.git Add Rcode response statistics on API - Add new statistic variable about rcode responses - Add metrics about RCode on statistics API entrypoint - Update regression tests --- diff --git a/pdns/responsestats-auth.cc b/pdns/responsestats-auth.cc index 2112dce2a6..61b4c6b008 100644 --- a/pdns/responsestats-auth.cc +++ b/pdns/responsestats-auth.cc @@ -52,5 +52,5 @@ void ResponseStats::submitResponse(DNSPacket &p, bool udpOrTCP) { } } - submitResponse(p.qtype.getCode(), buf.length(), udpOrTCP); + submitResponse(p.qtype.getCode(), buf.length(), p.d.rcode, udpOrTCP); } diff --git a/pdns/responsestats.cc b/pdns/responsestats.cc index 64ec3abe45..93b2fca511 100644 --- a/pdns/responsestats.cc +++ b/pdns/responsestats.cc @@ -8,7 +8,7 @@ #include "dnsparser.hh" -ResponseStats::ResponseStats() : d_qtypecounters(new std::atomic[65536]) +ResponseStats::ResponseStats() : d_qtypecounters(new std::atomic[65536]), d_rcodecounters(new std::atomic[256]) { d_sizecounters.push_back(make_pair(20,0)); d_sizecounters.push_back(make_pair(40,0)); @@ -21,6 +21,8 @@ ResponseStats::ResponseStats() : d_qtypecounters(new std::atomic::max(),0)); for(unsigned int n =0 ; n < 65535; ++n) d_qtypecounters[n] = 0; + for(unsigned int n =0 ; n < 256; ++n) + d_rcodecounters[n] = 0; } ResponseStats g_rs; @@ -28,9 +30,15 @@ ResponseStats g_rs; static bool pcomp(const pair&a , const pair&b) { return a.first < b.first; -} +} + +void ResponseStats::submitResponse(uint16_t qtype,uint16_t respsize, uint8_t rcode, bool udpOrTCP) +{ + d_rcodecounters[rcode]++; + submitResponse(qtype, respsize, udpOrTCP); +} -void ResponseStats::submitResponse(uint16_t qtype, uint16_t respsize, bool udpOrTCP) +void ResponseStats::submitResponse(uint16_t qtype,uint16_t respsize, bool udpOrTCP) { d_qtypecounters[qtype]++; pair s(respsize, 0); @@ -63,6 +71,18 @@ map ResponseStats::getSizeResponseCounts() return ret; } +map ResponseStats::getRCodeResponseCounts() +{ + map ret; + uint64_t count; + for(unsigned int i = 0 ; i < 256 ; ++i) { + count= d_rcodecounters[i]; + if(count) + ret[i]=count; + } + return ret; +} + string ResponseStats::getQTypeReport() { typedef map qtypenums_t; @@ -74,4 +94,3 @@ string ResponseStats::getQTypeReport() } return os.str(); } - diff --git a/pdns/responsestats.hh b/pdns/responsestats.hh index c82cf05c14..884d49d0f2 100644 --- a/pdns/responsestats.hh +++ b/pdns/responsestats.hh @@ -30,12 +30,15 @@ public: void submitResponse(DNSPacket &p, bool udpOrTCP); void submitResponse(uint16_t qtype, uint16_t respsize, bool udpOrTCP); + void submitResponse(uint16_t qtype, uint16_t respsize, uint8_t rcode, bool udpOrTCP); map getQTypeResponseCounts(); map getSizeResponseCounts(); + map getRCodeResponseCounts(); string getQTypeReport(); private: boost::scoped_array> d_qtypecounters; + boost::scoped_array> d_rcodecounters; typedef vector > sizecounters_t; sizecounters_t d_sizecounters; }; diff --git a/pdns/ws-api.cc b/pdns/ws-api.cc index 54776cd1e3..6106d25f33 100644 --- a/pdns/ws-api.cc +++ b/pdns/ws-api.cc @@ -165,6 +165,7 @@ void apiServerStatistics(HttpRequest* req, HttpResponse* resp) { auto resp_qtype_stats = g_rs.getQTypeResponseCounts(); auto resp_size_stats = g_rs.getSizeResponseCounts(); + auto resp_rcode_stats = g_rs.getRCodeResponseCounts(); Json::array doc; for(const auto& item : general_stats) { @@ -188,7 +189,7 @@ void apiServerStatistics(HttpRequest* req, HttpResponse* resp) { doc.push_back(Json::object { { "type", "MapStatisticItem" }, - { "name", "queries-by-qtype" }, + { "name", "response-by-qtype" }, { "value", values }, }); } @@ -212,6 +213,24 @@ void apiServerStatistics(HttpRequest* req, HttpResponse* resp) { }); } + { + Json::array values; + for(const auto& item : resp_rcode_stats) { + if (item.second == 0) + continue; + values.push_back(Json::object { + { "name", RCode::to_s(item.first) }, + { "value", std::to_string(item.second) }, + }); + } + + doc.push_back(Json::object { + { "type", "MapStatisticItem" }, + { "name", "response-by-rcode" }, + { "value", values }, + }); + } + #ifndef RECURSOR for(const auto& ringName : S.listRings()) { Json::array values; diff --git a/regression-tests.api/test_Servers.py b/regression-tests.api/test_Servers.py index 400a6e47fd..80835f999e 100644 --- a/regression-tests.api/test_Servers.py +++ b/regression-tests.api/test_Servers.py @@ -43,14 +43,17 @@ class Servers(ApiTestCase): self.assertIn('uptime', [e['name'] for e in data]) if is_auth(): print(data) - qtype_stats, respsize_stats, queries_stats = None, None, None + qtype_stats, respsize_stats, queries_stats, rcode_stats = None, None, None, None for elem in data: - if elem['type'] == 'MapStatisticItem' and elem['name'] == 'queries-by-qtype': + if elem['type'] == 'MapStatisticItem' and elem['name'] == 'response-by-qtype': qtype_stats = elem['value'] elif elem['type'] == 'MapStatisticItem' and elem['name'] == 'response-sizes': respsize_stats = elem['value'] elif elem['type'] == 'RingStatisticItem' and elem['name'] == 'queries': queries_stats = elem['value'] + elif elem['type'] == 'MapStatisticItem' and elem['name'] == 'response-by-rcode': + rcode_stats = elem['value'] self.assertIn('A', [e['name'] for e in qtype_stats]) self.assertIn('60', [e['name'] for e in respsize_stats]) self.assertIn('example.com/A', [e['name'] for e in queries_stats]) + self.assertIn('No Error', [e['name'] for e in rcode_stats])