/src/pdns/pdns/statbag.cc
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * This file is part of PowerDNS or dnsdist. |
3 | | * Copyright -- PowerDNS.COM B.V. and its contributors |
4 | | * |
5 | | * This program is free software; you can redistribute it and/or modify |
6 | | * it under the terms of version 2 of the GNU General Public License as |
7 | | * published by the Free Software Foundation. |
8 | | * |
9 | | * In addition, for the avoidance of any doubt, permission is granted to |
10 | | * link this program with OpenSSL and to (re)distribute the binaries |
11 | | * produced as the result of such linking. |
12 | | * |
13 | | * This program is distributed in the hope that it will be useful, |
14 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 | | * GNU General Public License for more details. |
17 | | * |
18 | | * You should have received a copy of the GNU General Public License |
19 | | * along with this program; if not, write to the Free Software |
20 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
21 | | */ |
22 | | #ifdef HAVE_CONFIG_H |
23 | | #include "config.h" |
24 | | #endif |
25 | | #include "utility.hh" |
26 | | #include "statbag.hh" |
27 | | #include "pdnsexception.hh" |
28 | | #include <iostream> |
29 | | #include <sstream> |
30 | | #include <algorithm> |
31 | | #include <utility> |
32 | | #include "arguments.hh" |
33 | | #include "lock.hh" |
34 | | #include "iputils.hh" |
35 | | |
36 | | |
37 | | #include "namespaces.hh" |
38 | | |
39 | | StatBag::StatBag() |
40 | 6 | { |
41 | 6 | d_doRings=false; |
42 | 6 | d_allowRedeclare=false; |
43 | 6 | } |
44 | | |
45 | | void StatBag::exists(const string &key) |
46 | 0 | { |
47 | 0 | if (!d_keyDescriptions.count(key)) { |
48 | 0 | throw PDNSException("Trying to deposit into unknown StatBag key '"+key+"'"); |
49 | 0 | } |
50 | 0 | } |
51 | | |
52 | | string StatBag::directory(const string &prefix) |
53 | 0 | { |
54 | 0 | string dir; |
55 | 0 | ostringstream o; |
56 | |
|
57 | 0 | for(const auto& val : d_stats) { |
58 | 0 | if (d_blacklist.find(val.first) != d_blacklist.end()) |
59 | 0 | continue; |
60 | 0 | if (val.first.find(prefix) != 0) |
61 | 0 | continue; |
62 | 0 | o << val.first<<"="<<*(val.second)<<","; |
63 | 0 | } |
64 | | |
65 | |
|
66 | 0 | for(const funcstats_t::value_type& val : d_funcstats) { |
67 | 0 | if (d_blacklist.find(val.first) != d_blacklist.end()) |
68 | 0 | continue; |
69 | 0 | if (val.first.find(prefix) != 0) |
70 | 0 | continue; |
71 | 0 | o << val.first<<"="<<val.second(val.first)<<","; |
72 | 0 | } |
73 | 0 | dir=o.str(); |
74 | 0 | return dir; |
75 | 0 | } |
76 | | |
77 | | vector<string>StatBag::getEntries() |
78 | 0 | { |
79 | 0 | vector<string> ret; |
80 | |
|
81 | 0 | for(const auto& i: d_stats) { |
82 | 0 | if (d_blacklist.find(i.first) != d_blacklist.end()) |
83 | 0 | continue; |
84 | 0 | ret.push_back(i.first); |
85 | 0 | } |
86 | |
|
87 | 0 | for(const funcstats_t::value_type& val : d_funcstats) { |
88 | 0 | if (d_blacklist.find(val.first) != d_blacklist.end()) |
89 | 0 | continue; |
90 | 0 | ret.push_back(val.first); |
91 | 0 | } |
92 | | |
93 | |
|
94 | 0 | return ret; |
95 | |
|
96 | 0 | } |
97 | | |
98 | | string StatBag::getDescrip(const string &item) |
99 | 0 | { |
100 | 0 | exists(item); |
101 | 0 | return d_keyDescriptions[item]; |
102 | 0 | } |
103 | | |
104 | | StatType StatBag::getStatType(const string &item) |
105 | 0 | { |
106 | 0 | exists(item); |
107 | 0 | return d_statTypes[item]; |
108 | 0 | } |
109 | | |
110 | | void StatBag::declare(const string &key, const string &descrip, StatType statType) |
111 | 0 | { |
112 | 0 | if(d_stats.count(key)) { |
113 | 0 | if (d_allowRedeclare) { |
114 | 0 | *d_stats[key] = 0; |
115 | 0 | return; |
116 | 0 | } |
117 | 0 | else { |
118 | 0 | throw PDNSException("Attempt to re-declare statbag '"+key+"'"); |
119 | 0 | } |
120 | 0 | } |
121 | | |
122 | 0 | auto i=make_unique<AtomicCounter>(0); |
123 | 0 | d_stats[key]=std::move(i); |
124 | 0 | d_keyDescriptions[key]=descrip; |
125 | 0 | d_statTypes[key]=statType; |
126 | 0 | } |
127 | | |
128 | | void StatBag::declare(const string &key, const string &descrip, StatBag::func_t func, StatType statType) |
129 | 0 | { |
130 | 0 | if(d_funcstats.count(key) && !d_allowRedeclare) { |
131 | 0 | throw PDNSException("Attempt to re-declare func statbag '"+key+"'"); |
132 | 0 | } |
133 | | |
134 | 0 | d_funcstats[key]=std::move(func); |
135 | 0 | d_keyDescriptions[key]=descrip; |
136 | 0 | d_statTypes[key]=statType; |
137 | 0 | } |
138 | | |
139 | | |
140 | | void StatBag::set(const string &key, unsigned long value) |
141 | 0 | { |
142 | 0 | exists(key); |
143 | 0 | d_stats[key]->store(value); |
144 | 0 | } |
145 | | |
146 | | unsigned long StatBag::read(const string &key) |
147 | 0 | { |
148 | 0 | exists(key); |
149 | 0 | funcstats_t::const_iterator iter = d_funcstats.find(key); |
150 | 0 | if (iter != d_funcstats.end()) { |
151 | 0 | return iter->second(iter->first); |
152 | 0 | } |
153 | 0 | return *d_stats[key]; |
154 | 0 | } |
155 | | |
156 | | string StatBag::getValueStr(const string &key) |
157 | 0 | { |
158 | 0 | ostringstream o; |
159 | 0 | o<<read(key); |
160 | 0 | return o.str(); |
161 | 0 | } |
162 | | |
163 | | AtomicCounter *StatBag::getPointer(const string &key) |
164 | 0 | { |
165 | 0 | exists(key); |
166 | 0 | return d_stats[key].get(); |
167 | 0 | } |
168 | | |
169 | | StatBag::~StatBag() |
170 | 0 | { |
171 | 0 | } |
172 | | |
173 | | template<typename T, typename Comp> |
174 | | StatRing<T,Comp>::StatRing(unsigned int size) |
175 | 0 | { |
176 | 0 | d_items.set_capacity(size); |
177 | 0 | } Unexecuted instantiation: StatRing<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, CIStringCompare>::StatRing(unsigned int) Unexecuted instantiation: StatRing<SComboAddress, std::__1::less<SComboAddress> >::StatRing(unsigned int) Unexecuted instantiation: StatRing<std::__1::tuple<DNSName, QType>, std::__1::less<std::__1::tuple<DNSName, QType> > >::StatRing(unsigned int) |
178 | | |
179 | | template<typename T, typename Comp> |
180 | | void StatRing<T,Comp>::account(const T& t) |
181 | 0 | { |
182 | 0 | d_items.push_back(t); |
183 | 0 | } Unexecuted instantiation: StatRing<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, CIStringCompare>::account(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) Unexecuted instantiation: StatRing<SComboAddress, std::__1::less<SComboAddress> >::account(SComboAddress const&) Unexecuted instantiation: StatRing<std::__1::tuple<DNSName, QType>, std::__1::less<std::__1::tuple<DNSName, QType> > >::account(std::__1::tuple<DNSName, QType> const&) |
184 | | |
185 | | template<typename T, typename Comp> |
186 | | uint64_t StatRing<T,Comp>::getSize() const |
187 | 0 | { |
188 | 0 | return d_items.capacity(); |
189 | 0 | } Unexecuted instantiation: StatRing<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, CIStringCompare>::getSize() const Unexecuted instantiation: StatRing<SComboAddress, std::__1::less<SComboAddress> >::getSize() const Unexecuted instantiation: StatRing<std::__1::tuple<DNSName, QType>, std::__1::less<std::__1::tuple<DNSName, QType> > >::getSize() const |
190 | | |
191 | | template<typename T, typename Comp> |
192 | | uint64_t StatRing<T,Comp>::getEntriesCount() const |
193 | 0 | { |
194 | 0 | return d_items.size(); |
195 | 0 | } Unexecuted instantiation: StatRing<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, CIStringCompare>::getEntriesCount() const Unexecuted instantiation: StatRing<SComboAddress, std::__1::less<SComboAddress> >::getEntriesCount() const Unexecuted instantiation: StatRing<std::__1::tuple<DNSName, QType>, std::__1::less<std::__1::tuple<DNSName, QType> > >::getEntriesCount() const |
196 | | |
197 | | template<typename T, typename Comp> |
198 | | void StatRing<T,Comp>::resize(unsigned int newsize) |
199 | 0 | { |
200 | 0 | d_items.set_capacity(newsize); |
201 | 0 | } Unexecuted instantiation: StatRing<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, CIStringCompare>::resize(unsigned int) Unexecuted instantiation: StatRing<SComboAddress, std::__1::less<SComboAddress> >::resize(unsigned int) Unexecuted instantiation: StatRing<std::__1::tuple<DNSName, QType>, std::__1::less<std::__1::tuple<DNSName, QType> > >::resize(unsigned int) |
202 | | |
203 | | template<typename T, typename Comp> |
204 | | void StatRing<T,Comp>::setHelp(const string &str) |
205 | 0 | { |
206 | 0 | d_help = str; |
207 | 0 | } Unexecuted instantiation: StatRing<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, CIStringCompare>::setHelp(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) Unexecuted instantiation: StatRing<SComboAddress, std::__1::less<SComboAddress> >::setHelp(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) Unexecuted instantiation: StatRing<std::__1::tuple<DNSName, QType>, std::__1::less<std::__1::tuple<DNSName, QType> > >::setHelp(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) |
208 | | |
209 | | template<typename T, typename Comp> |
210 | | string StatRing<T,Comp>::getHelp() const |
211 | 0 | { |
212 | 0 | return d_help; |
213 | 0 | } Unexecuted instantiation: StatRing<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, CIStringCompare>::getHelp() const Unexecuted instantiation: StatRing<SComboAddress, std::__1::less<SComboAddress> >::getHelp() const Unexecuted instantiation: StatRing<std::__1::tuple<DNSName, QType>, std::__1::less<std::__1::tuple<DNSName, QType> > >::getHelp() const |
214 | | |
215 | | |
216 | | template<typename T, typename Comp> |
217 | | vector<pair<T, unsigned int> >StatRing<T,Comp>::get() const |
218 | 0 | { |
219 | 0 | map<T,unsigned int, Comp> res; |
220 | 0 | for (typename boost::circular_buffer<T>::const_iterator i = d_items.begin(); i != d_items.end(); ++i) { |
221 | 0 | res[*i]++; |
222 | 0 | } |
223 | | |
224 | 0 | vector<pair<T ,unsigned int> > tmp; |
225 | 0 | for(typename map<T, unsigned int>::const_iterator i=res.begin();i!=res.end();++i) |
226 | 0 | tmp.push_back(*i); |
227 | |
|
228 | 0 | sort(tmp.begin(),tmp.end(),popisort); |
229 | |
|
230 | 0 | return tmp; |
231 | 0 | } Unexecuted instantiation: StatRing<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, CIStringCompare>::get() const Unexecuted instantiation: StatRing<SComboAddress, std::__1::less<SComboAddress> >::get() const Unexecuted instantiation: StatRing<std::__1::tuple<DNSName, QType>, std::__1::less<std::__1::tuple<DNSName, QType> > >::get() const |
232 | | |
233 | | void StatBag::registerRingStats(const string& name) |
234 | 0 | { |
235 | 0 | declare("ring-" + name + "-size", "Number of entries in the " + name + " ring", [this,name](const std::string&) { return static_cast<uint64_t>(getRingEntriesCount(name)); }, StatType::gauge); |
236 | 0 | declare("ring-" + name + "-capacity", "Maximum number of entries in the " + name + " ring", [this,name](const std::string&) { return static_cast<uint64_t>(getRingSize(name)); }, StatType::gauge); |
237 | 0 | } |
238 | | |
239 | | void StatBag::declareRing(const string &name, const string &help, unsigned int size) |
240 | 0 | { |
241 | 0 | d_rings.emplace(name, size); |
242 | 0 | d_rings[name].lock()->setHelp(help); |
243 | 0 | registerRingStats(name); |
244 | 0 | } |
245 | | |
246 | | void StatBag::declareComboRing(const string &name, const string &help, unsigned int size) |
247 | 0 | { |
248 | 0 | d_comboRings.emplace(name, size); |
249 | 0 | d_comboRings[name].lock()->setHelp(help); |
250 | 0 | registerRingStats(name); |
251 | 0 | } |
252 | | |
253 | | void StatBag::declareDNSNameQTypeRing(const string &name, const string &help, unsigned int size) |
254 | 0 | { |
255 | 0 | d_dnsnameqtyperings.emplace(name, size); |
256 | 0 | d_dnsnameqtyperings[name].lock()->setHelp(help); |
257 | 0 | registerRingStats(name); |
258 | 0 | } |
259 | | |
260 | | vector<pair<string, unsigned int> > StatBag::getRing(const string &name) |
261 | 0 | { |
262 | 0 | if (d_rings.count(name)) { |
263 | 0 | return d_rings[name].lock()->get(); |
264 | 0 | } |
265 | 0 | vector<pair<string, unsigned int> > ret; |
266 | |
|
267 | 0 | if (d_comboRings.count(name)) { |
268 | 0 | typedef pair<SComboAddress, unsigned int> stor_t; |
269 | 0 | vector<stor_t> raw =d_comboRings[name].lock()->get(); |
270 | 0 | for(const stor_t& stor : raw) { |
271 | 0 | ret.emplace_back(stor.first.ca.toString(), stor.second); |
272 | 0 | } |
273 | 0 | } else if (d_dnsnameqtyperings.count(name)) { |
274 | 0 | auto raw = d_dnsnameqtyperings[name].lock()->get(); |
275 | 0 | for (auto const &e : raw) { |
276 | 0 | ret.emplace_back(std::get<0>(e.first).toLogString() + "/" + std::get<1>(e.first).toString(), e.second); |
277 | 0 | } |
278 | 0 | } |
279 | 0 | return ret; |
280 | 0 | } |
281 | | |
282 | | template<typename T, typename Comp> |
283 | | void StatRing<T,Comp>::reset() |
284 | 0 | { |
285 | 0 | d_items.clear(); |
286 | 0 | } Unexecuted instantiation: StatRing<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, CIStringCompare>::reset() Unexecuted instantiation: StatRing<SComboAddress, std::__1::less<SComboAddress> >::reset() Unexecuted instantiation: StatRing<std::__1::tuple<DNSName, QType>, std::__1::less<std::__1::tuple<DNSName, QType> > >::reset() |
287 | | |
288 | | void StatBag::resetRing(const string &name) |
289 | 0 | { |
290 | 0 | if(d_rings.count(name)) |
291 | 0 | d_rings[name].lock()->reset(); |
292 | 0 | if(d_comboRings.count(name)) |
293 | 0 | d_comboRings[name].lock()->reset(); |
294 | 0 | if(d_dnsnameqtyperings.count(name)) |
295 | 0 | d_dnsnameqtyperings[name].lock()->reset(); |
296 | 0 | } |
297 | | |
298 | | void StatBag::resizeRing(const string &name, unsigned int newsize) |
299 | 0 | { |
300 | 0 | if(d_rings.count(name)) |
301 | 0 | d_rings[name].lock()->resize(newsize); |
302 | 0 | if(d_comboRings.count(name)) |
303 | 0 | d_comboRings[name].lock()->resize(newsize); |
304 | 0 | if(d_dnsnameqtyperings.count(name)) |
305 | 0 | return d_dnsnameqtyperings[name].lock()->resize(newsize); |
306 | 0 | } |
307 | | |
308 | | |
309 | | uint64_t StatBag::getRingSize(const string &name) |
310 | 0 | { |
311 | 0 | if(d_rings.count(name)) |
312 | 0 | return d_rings[name].lock()->getSize(); |
313 | 0 | if(d_comboRings.count(name)) |
314 | 0 | return d_comboRings[name].lock()->getSize(); |
315 | 0 | if(d_dnsnameqtyperings.count(name)) |
316 | 0 | return d_dnsnameqtyperings[name].lock()->getSize(); |
317 | 0 | return 0; |
318 | 0 | } |
319 | | |
320 | | uint64_t StatBag::getRingEntriesCount(const string &name) |
321 | 0 | { |
322 | 0 | if(d_rings.count(name)) |
323 | 0 | return d_rings[name].lock()->getEntriesCount(); |
324 | 0 | if(d_comboRings.count(name)) |
325 | 0 | return d_comboRings[name].lock()->getEntriesCount(); |
326 | 0 | if(d_dnsnameqtyperings.count(name)) |
327 | 0 | return d_dnsnameqtyperings[name].lock()->getEntriesCount(); |
328 | 0 | return 0; |
329 | 0 | } |
330 | | |
331 | | string StatBag::getRingTitle(const string &name) |
332 | 0 | { |
333 | 0 | if(d_rings.count(name)) |
334 | 0 | return d_rings[name].lock()->getHelp(); |
335 | 0 | if(d_comboRings.count(name)) |
336 | 0 | return d_comboRings[name].lock()->getHelp(); |
337 | 0 | if(d_dnsnameqtyperings.count(name)) |
338 | 0 | return d_dnsnameqtyperings[name].lock()->getHelp(); |
339 | 0 | return ""; |
340 | 0 | } |
341 | | |
342 | | vector<string>StatBag::listRings() const |
343 | 0 | { |
344 | 0 | vector<string> ret; |
345 | 0 | for(auto & d_ring : d_rings) |
346 | 0 | ret.push_back(d_ring.first); |
347 | 0 | for(auto & d_comboRing : d_comboRings) |
348 | 0 | ret.push_back(d_comboRing.first); |
349 | 0 | for(const auto &i : d_dnsnameqtyperings) |
350 | 0 | ret.push_back(i.first); |
351 | |
|
352 | 0 | return ret; |
353 | 0 | } |
354 | | |
355 | | bool StatBag::ringExists(const string &name) const |
356 | 0 | { |
357 | 0 | return d_rings.count(name) || d_comboRings.count(name) || d_dnsnameqtyperings.count(name); |
358 | 0 | } |
359 | | |
360 | 0 | void StatBag::blacklist(const string& str) { |
361 | 0 | d_blacklist.insert(str); |
362 | 0 | } |
363 | | |
364 | | template class StatRing<std::string, CIStringCompare>; |
365 | | template class StatRing<SComboAddress>; |
366 | | template class StatRing<std::tuple<DNSName, QType> >; |