}
}
- submitResponse(p.qtype.getCode(), buf.length(), udpOrTCP);
+ submitResponse(p.qtype.getCode(), buf.length(), p.d.rcode, udpOrTCP);
}
#include "dnsparser.hh"
-ResponseStats::ResponseStats() : d_qtypecounters(new std::atomic<unsigned long>[65536])
+ResponseStats::ResponseStats() : d_qtypecounters(new std::atomic<unsigned long>[65536]), d_rcodecounters(new std::atomic<unsigned long>[256])
{
d_sizecounters.push_back(make_pair(20,0));
d_sizecounters.push_back(make_pair(40,0));
d_sizecounters.push_back(make_pair(std::numeric_limits<uint16_t>::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;
static bool pcomp(const pair<uint16_t, uint64_t>&a , const pair<uint16_t, uint64_t>&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<uint16_t, uint64_t> s(respsize, 0);
return ret;
}
+map<uint8_t, uint64_t> ResponseStats::getRCodeResponseCounts()
+{
+ map<uint8_t, uint64_t> 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<uint16_t, uint64_t> qtypenums_t;
}
return os.str();
}
-
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<uint16_t, uint64_t> getQTypeResponseCounts();
map<uint16_t, uint64_t> getSizeResponseCounts();
+ map<uint8_t, uint64_t> getRCodeResponseCounts();
string getQTypeReport();
private:
boost::scoped_array<std::atomic<unsigned long>> d_qtypecounters;
+ boost::scoped_array<std::atomic<unsigned long>> d_rcodecounters;
typedef vector<pair<uint16_t, uint64_t> > sizecounters_t;
sizecounters_t d_sizecounters;
};
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) {
doc.push_back(Json::object {
{ "type", "MapStatisticItem" },
- { "name", "queries-by-qtype" },
+ { "name", "response-by-qtype" },
{ "value", values },
});
}
});
}
+ {
+ 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;
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])