]> git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/dnsdist-rings.cc
dnsdist: Make `topBandwidth()` behave like other top* functions
[thirdparty/pdns.git] / pdns / dnsdist-rings.cc
1 #include "dnsdist.hh"
2 #include "lock.hh"
3
4 unsigned int Rings::numDistinctRequestors()
5 {
6 std::set<ComboAddress, ComboAddress::addressOnlyLessThan> s;
7 ReadLock rl(&queryLock);
8 for(const auto& q : queryRing)
9 s.insert(q.requestor);
10 return s.size();
11 }
12
13 std::unordered_map<int, vector<boost::variant<string,double>>> Rings::getTopBandwidth(unsigned int numentries)
14 {
15 map<ComboAddress, unsigned int, ComboAddress::addressOnlyLessThan> counts;
16 uint64_t total=0;
17 {
18 ReadLock rl(&queryLock);
19 for(const auto& q : queryRing) {
20 counts[q.requestor]+=q.size;
21 total+=q.size;
22 }
23 }
24
25 {
26 std::lock_guard<std::mutex> lock(respMutex);
27 for(const auto& r : respRing) {
28 counts[r.requestor]+=r.size;
29 total+=r.size;
30 }
31 }
32
33 typedef vector<pair<unsigned int, ComboAddress>> ret_t;
34 ret_t rcounts;
35 rcounts.reserve(counts.size());
36 for(const auto& p : counts)
37 rcounts.push_back({p.second, p.first});
38 numentries = rcounts.size() < numentries ? rcounts.size() : numentries;
39 partial_sort(rcounts.begin(), rcounts.begin()+numentries, rcounts.end(), [](const ret_t::value_type&a, const ret_t::value_type&b)
40 {
41 return(b.first < a.first);
42 });
43 std::unordered_map<int, vector<boost::variant<string,double>>> ret;
44 uint64_t rest = 0;
45 unsigned int count = 1;
46 for(const auto& rc : rcounts) {
47 if(count==numentries+1) {
48 rest+=rc.first;
49 }
50 else {
51 ret.insert({count++, {rc.second.toString(), rc.first, 100.0*rc.first/total}});
52 }
53 }
54 ret.insert({count, {"Rest", rest, total > 0 ? 100.0*rest/total : 100.0}});
55 return ret;
56 }