]>
Commit | Line | Data |
---|---|---|
12c86877 | 1 | /* |
6edbf68a PL |
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 | */ | |
870a0fe4 AT |
22 | #ifdef HAVE_CONFIG_H |
23 | #include "config.h" | |
24 | #endif | |
896e5153 | 25 | #include "utility.hh" |
12c86877 | 26 | #include "statbag.hh" |
5c409fa2 | 27 | #include "pdnsexception.hh" |
12c86877 BH |
28 | #include <iostream> |
29 | #include <sstream> | |
30 | #include <algorithm> | |
4de01aaa | 31 | #include <utility> |
12c86877 BH |
32 | #include "arguments.hh" |
33 | #include "lock.hh" | |
4eb26e0f | 34 | #include "iputils.hh" |
fa8fd4d2 | 35 | |
12c86877 | 36 | |
10f4eea8 | 37 | #include "namespaces.hh" |
12c86877 BH |
38 | |
39 | StatBag::StatBag() | |
40 | { | |
41 | d_doRings=false; | |
dbbe10c3 | 42 | d_allowRedeclare=false; |
12c86877 BH |
43 | } |
44 | ||
12c86877 BH |
45 | void StatBag::exists(const string &key) |
46 | { | |
42b8372c RG |
47 | if (!d_keyDescriptions.count(key)) { |
48 | throw PDNSException("Trying to deposit into unknown StatBag key '"+key+"'"); | |
49 | } | |
12c86877 BH |
50 | } |
51 | ||
3ef5fc26 | 52 | string StatBag::directory(const string &prefix) |
12c86877 BH |
53 | { |
54 | string dir; | |
55 | ostringstream o; | |
1566533a | 56 | |
3ef5fc26 CH |
57 | for(const auto& val : d_stats) { |
58 | if (d_blacklist.find(val.first) != d_blacklist.end()) | |
28c3cc11 | 59 | continue; |
3ef5fc26 CH |
60 | if (val.first.find(prefix) != 0) |
61 | continue; | |
62 | o << val.first<<"="<<*(val.second)<<","; | |
cb167afd | 63 | } |
1566533a | 64 | |
e903706d | 65 | |
ef7cd021 | 66 | for(const funcstats_t::value_type& val : d_funcstats) { |
f3245c8c | 67 | if (d_blacklist.find(val.first) != d_blacklist.end()) |
28c3cc11 | 68 | continue; |
3ef5fc26 CH |
69 | if (val.first.find(prefix) != 0) |
70 | continue; | |
e903706d | 71 | o << val.first<<"="<<val.second(val.first)<<","; |
72 | } | |
12c86877 BH |
73 | dir=o.str(); |
74 | return dir; | |
75 | } | |
76 | ||
12c86877 BH |
77 | vector<string>StatBag::getEntries() |
78 | { | |
79 | vector<string> ret; | |
1566533a | 80 | |
cb167afd | 81 | for(const auto& i: d_stats) { |
f3245c8c OM |
82 | if (d_blacklist.find(i.first) != d_blacklist.end()) |
83 | continue; | |
84 | ret.push_back(i.first); | |
cb167afd | 85 | } |
12c86877 | 86 | |
ef7cd021 | 87 | for(const funcstats_t::value_type& val : d_funcstats) { |
f3245c8c OM |
88 | if (d_blacklist.find(val.first) != d_blacklist.end()) |
89 | continue; | |
e903706d | 90 | ret.push_back(val.first); |
91 | } | |
92 | ||
1566533a | 93 | |
12c86877 BH |
94 | return ret; |
95 | ||
96 | } | |
97 | ||
98 | string StatBag::getDescrip(const string &item) | |
99 | { | |
1566533a | 100 | exists(item); |
06f46d0a | 101 | return d_keyDescriptions[item]; |
12c86877 BH |
102 | } |
103 | ||
dec69610 MTH |
104 | StatType StatBag::getStatType(const string &item) |
105 | { | |
106 | exists(item); | |
107 | return d_statTypes[item]; | |
108 | } | |
109 | ||
33b222ed | 110 | void StatBag::declare(const string &key, const string &descrip, StatType statType) |
12c86877 | 111 | { |
c1882542 | 112 | if(d_stats.count(key)) { |
dbbe10c3 PD |
113 | if (d_allowRedeclare) { |
114 | *d_stats[key] = 0; | |
115 | return; | |
116 | } | |
117 | else { | |
118 | throw PDNSException("Attempt to re-declare statbag '"+key+"'"); | |
119 | } | |
c1882542 PD |
120 | } |
121 | ||
c2826d2e RG |
122 | auto i=make_unique<AtomicCounter>(0); |
123 | d_stats[key]=std::move(i); | |
06f46d0a | 124 | d_keyDescriptions[key]=descrip; |
33b222ed | 125 | d_statTypes[key]=statType; |
12c86877 BH |
126 | } |
127 | ||
dec69610 | 128 | void StatBag::declare(const string &key, const string &descrip, StatBag::func_t func, StatType statType) |
e903706d | 129 | { |
dbbe10c3 PD |
130 | if(d_funcstats.count(key) && !d_allowRedeclare) { |
131 | throw PDNSException("Attempt to re-declare func statbag '"+key+"'"); | |
132 | } | |
133 | ||
4de01aaa | 134 | d_funcstats[key]=std::move(func); |
06f46d0a | 135 | d_keyDescriptions[key]=descrip; |
dec69610 | 136 | d_statTypes[key]=statType; |
e903706d | 137 | } |
12c86877 BH |
138 | |
139 | ||
ac0995bb | 140 | void StatBag::set(const string &key, unsigned long value) |
12c86877 | 141 | { |
12c86877 | 142 | exists(key); |
ac0995bb | 143 | d_stats[key]->store(value); |
12c86877 BH |
144 | } |
145 | ||
ac0995bb | 146 | unsigned long StatBag::read(const string &key) |
12c86877 | 147 | { |
1566533a | 148 | exists(key); |
3b433571 | 149 | funcstats_t::const_iterator iter = d_funcstats.find(key); |
42b8372c | 150 | if (iter != d_funcstats.end()) { |
3b433571 | 151 | return iter->second(iter->first); |
42b8372c | 152 | } |
1566533a | 153 | return *d_stats[key]; |
12c86877 BH |
154 | } |
155 | ||
12c86877 BH |
156 | string StatBag::getValueStr(const string &key) |
157 | { | |
158 | ostringstream o; | |
159 | o<<read(key); | |
160 | return o.str(); | |
161 | } | |
162 | ||
1566533a | 163 | AtomicCounter *StatBag::getPointer(const string &key) |
12c86877 BH |
164 | { |
165 | exists(key); | |
c2826d2e | 166 | return d_stats[key].get(); |
12c86877 BH |
167 | } |
168 | ||
abb11ca4 | 169 | StatBag::~StatBag() = default; |
12c86877 | 170 | |
4eb26e0f | 171 | template<typename T, typename Comp> |
172 | StatRing<T,Comp>::StatRing(unsigned int size) | |
12c86877 | 173 | { |
4eb26e0f | 174 | d_items.set_capacity(size); |
12c86877 BH |
175 | } |
176 | ||
4eb26e0f | 177 | template<typename T, typename Comp> |
178 | void StatRing<T,Comp>::account(const T& t) | |
12c86877 | 179 | { |
4eb26e0f | 180 | d_items.push_back(t); |
181 | } | |
12c86877 | 182 | |
4eb26e0f | 183 | template<typename T, typename Comp> |
74e38357 | 184 | uint64_t StatRing<T,Comp>::getSize() const |
4eb26e0f | 185 | { |
4eb26e0f | 186 | return d_items.capacity(); |
12c86877 | 187 | } |
975bee12 | 188 | |
74e38357 RG |
189 | template<typename T, typename Comp> |
190 | uint64_t StatRing<T,Comp>::getEntriesCount() const | |
191 | { | |
74e38357 RG |
192 | return d_items.size(); |
193 | } | |
194 | ||
4eb26e0f | 195 | template<typename T, typename Comp> |
196 | void StatRing<T,Comp>::resize(unsigned int newsize) | |
12c86877 | 197 | { |
4eb26e0f | 198 | d_items.set_capacity(newsize); |
12c86877 BH |
199 | } |
200 | ||
4eb26e0f | 201 | template<typename T, typename Comp> |
202 | void StatRing<T,Comp>::setHelp(const string &str) | |
12c86877 | 203 | { |
42b8372c | 204 | d_help = str; |
12c86877 BH |
205 | } |
206 | ||
4eb26e0f | 207 | template<typename T, typename Comp> |
42b8372c | 208 | string StatRing<T,Comp>::getHelp() const |
12c86877 BH |
209 | { |
210 | return d_help; | |
211 | } | |
212 | ||
12c86877 | 213 | |
4eb26e0f | 214 | template<typename T, typename Comp> |
215 | vector<pair<T, unsigned int> >StatRing<T,Comp>::get() const | |
12c86877 | 216 | { |
4eb26e0f | 217 | map<T,unsigned int, Comp> res; |
1620901c | 218 | for (typename boost::circular_buffer<T>::const_iterator i = d_items.begin(); i != d_items.end(); ++i) { |
4eb26e0f | 219 | res[*i]++; |
12c86877 BH |
220 | } |
221 | ||
4eb26e0f | 222 | vector<pair<T ,unsigned int> > tmp; |
223 | for(typename map<T, unsigned int>::const_iterator i=res.begin();i!=res.end();++i) | |
12c86877 BH |
224 | tmp.push_back(*i); |
225 | ||
226 | sort(tmp.begin(),tmp.end(),popisort); | |
227 | ||
228 | return tmp; | |
229 | } | |
230 | ||
74e38357 RG |
231 | void StatBag::registerRingStats(const string& name) |
232 | { | |
13e6a268 | 233 | 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); |
32a64e37 | 234 | 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); |
74e38357 RG |
235 | } |
236 | ||
12c86877 BH |
237 | void StatBag::declareRing(const string &name, const string &help, unsigned int size) |
238 | { | |
92b91988 | 239 | d_rings.emplace(name, size); |
42b8372c | 240 | d_rings[name].lock()->setHelp(help); |
74e38357 | 241 | registerRingStats(name); |
12c86877 BH |
242 | } |
243 | ||
4eb26e0f | 244 | void StatBag::declareComboRing(const string &name, const string &help, unsigned int size) |
12c86877 | 245 | { |
ef2ea4bf | 246 | d_comboRings.emplace(name, size); |
42b8372c | 247 | d_comboRings[name].lock()->setHelp(help); |
74e38357 | 248 | registerRingStats(name); |
12c86877 BH |
249 | } |
250 | ||
f2b2f3ad PL |
251 | void StatBag::declareDNSNameQTypeRing(const string &name, const string &help, unsigned int size) |
252 | { | |
92b91988 | 253 | d_dnsnameqtyperings.emplace(name, size); |
42b8372c | 254 | d_dnsnameqtyperings[name].lock()->setHelp(help); |
74e38357 | 255 | registerRingStats(name); |
f2b2f3ad PL |
256 | } |
257 | ||
4eb26e0f | 258 | vector<pair<string, unsigned int> > StatBag::getRing(const string &name) |
12c86877 | 259 | { |
42b8372c RG |
260 | if (d_rings.count(name)) { |
261 | return d_rings[name].lock()->get(); | |
f2b2f3ad PL |
262 | } |
263 | vector<pair<string, unsigned int> > ret; | |
264 | ||
ef2ea4bf | 265 | if (d_comboRings.count(name)) { |
74d85173 RP |
266 | for (const auto& [addr, num] : d_comboRings[name].lock()->get()) { |
267 | ret.emplace_back(addr.ca.toString(), num); | |
4eb26e0f | 268 | } |
42b8372c | 269 | } else if (d_dnsnameqtyperings.count(name)) { |
74d85173 RP |
270 | for (auto const& [d, t] : d_dnsnameqtyperings[name].lock()->get()) { |
271 | ret.emplace_back(std::get<0>(d).toLogString() + "/" + std::get<1>(d).toString(), t); | |
f2b2f3ad | 272 | } |
12c86877 | 273 | } |
f2b2f3ad | 274 | return ret; |
4eb26e0f | 275 | } |
276 | ||
277 | template<typename T, typename Comp> | |
278 | void StatRing<T,Comp>::reset() | |
279 | { | |
4eb26e0f | 280 | d_items.clear(); |
12c86877 BH |
281 | } |
282 | ||
283 | void StatBag::resetRing(const string &name) | |
284 | { | |
4eb26e0f | 285 | if(d_rings.count(name)) |
42b8372c | 286 | d_rings[name].lock()->reset(); |
ef2ea4bf | 287 | if(d_comboRings.count(name)) |
42b8372c | 288 | d_comboRings[name].lock()->reset(); |
f2b2f3ad | 289 | if(d_dnsnameqtyperings.count(name)) |
42b8372c | 290 | d_dnsnameqtyperings[name].lock()->reset(); |
12c86877 BH |
291 | } |
292 | ||
bb3c3f50 | 293 | void StatBag::resizeRing(const string &name, unsigned int newsize) |
12c86877 | 294 | { |
4eb26e0f | 295 | if(d_rings.count(name)) |
42b8372c | 296 | d_rings[name].lock()->resize(newsize); |
ef2ea4bf | 297 | if(d_comboRings.count(name)) |
42b8372c | 298 | d_comboRings[name].lock()->resize(newsize); |
f2b2f3ad | 299 | if(d_dnsnameqtyperings.count(name)) |
42b8372c | 300 | return d_dnsnameqtyperings[name].lock()->resize(newsize); |
12c86877 BH |
301 | } |
302 | ||
303 | ||
74e38357 | 304 | uint64_t StatBag::getRingSize(const string &name) |
12c86877 | 305 | { |
4eb26e0f | 306 | if(d_rings.count(name)) |
42b8372c | 307 | return d_rings[name].lock()->getSize(); |
ef2ea4bf | 308 | if(d_comboRings.count(name)) |
42b8372c | 309 | return d_comboRings[name].lock()->getSize(); |
f2b2f3ad | 310 | if(d_dnsnameqtyperings.count(name)) |
42b8372c | 311 | return d_dnsnameqtyperings[name].lock()->getSize(); |
f2b2f3ad | 312 | return 0; |
12c86877 BH |
313 | } |
314 | ||
74e38357 RG |
315 | uint64_t StatBag::getRingEntriesCount(const string &name) |
316 | { | |
317 | if(d_rings.count(name)) | |
42b8372c | 318 | return d_rings[name].lock()->getEntriesCount(); |
ef2ea4bf | 319 | if(d_comboRings.count(name)) |
42b8372c | 320 | return d_comboRings[name].lock()->getEntriesCount(); |
74e38357 | 321 | if(d_dnsnameqtyperings.count(name)) |
42b8372c | 322 | return d_dnsnameqtyperings[name].lock()->getEntriesCount(); |
74e38357 RG |
323 | return 0; |
324 | } | |
325 | ||
12c86877 BH |
326 | string StatBag::getRingTitle(const string &name) |
327 | { | |
4eb26e0f | 328 | if(d_rings.count(name)) |
42b8372c | 329 | return d_rings[name].lock()->getHelp(); |
ef2ea4bf | 330 | if(d_comboRings.count(name)) |
42b8372c | 331 | return d_comboRings[name].lock()->getHelp(); |
f2b2f3ad | 332 | if(d_dnsnameqtyperings.count(name)) |
42b8372c | 333 | return d_dnsnameqtyperings[name].lock()->getHelp(); |
f2b2f3ad | 334 | return ""; |
12c86877 BH |
335 | } |
336 | ||
42b8372c | 337 | vector<string>StatBag::listRings() const |
12c86877 BH |
338 | { |
339 | vector<string> ret; | |
d7f67000 RP |
340 | for(auto & d_ring : d_rings) |
341 | ret.push_back(d_ring.first); | |
342 | for(auto & d_comboRing : d_comboRings) | |
343 | ret.push_back(d_comboRing.first); | |
f2b2f3ad PL |
344 | for(const auto &i : d_dnsnameqtyperings) |
345 | ret.push_back(i.first); | |
4eb26e0f | 346 | |
12c86877 BH |
347 | return ret; |
348 | } | |
349 | ||
42b8372c | 350 | bool StatBag::ringExists(const string &name) const |
ef1439ff | 351 | { |
ef2ea4bf | 352 | return d_rings.count(name) || d_comboRings.count(name) || d_dnsnameqtyperings.count(name); |
ef1439ff | 353 | } |
4eb26e0f | 354 | |
f3245c8c OM |
355 | void StatBag::blacklist(const string& str) { |
356 | d_blacklist.insert(str); | |
357 | } | |
358 | ||
fadd04cc | 359 | template class StatRing<std::string, CIStringCompare>; |
662d5441 | 360 | template class StatRing<SComboAddress>; |
f2b2f3ad | 361 | template class StatRing<std::tuple<DNSName, QType> >; |