]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/statbag.cc
Merge pull request #14021 from Habbie/auth-lua-join-whitespace
[thirdparty/pdns.git] / pdns / statbag.cc
CommitLineData
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
39StatBag::StatBag()
40{
41 d_doRings=false;
dbbe10c3 42 d_allowRedeclare=false;
12c86877
BH
43}
44
12c86877
BH
45void 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 52string 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
77vector<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
98string StatBag::getDescrip(const string &item)
99{
1566533a 100 exists(item);
06f46d0a 101 return d_keyDescriptions[item];
12c86877
BH
102}
103
dec69610
MTH
104StatType StatBag::getStatType(const string &item)
105{
106 exists(item);
107 return d_statTypes[item];
108}
109
33b222ed 110void 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 128void 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 140void 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 146unsigned 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
156string StatBag::getValueStr(const string &key)
157{
158 ostringstream o;
159 o<<read(key);
160 return o.str();
161}
162
1566533a 163AtomicCounter *StatBag::getPointer(const string &key)
12c86877
BH
164{
165 exists(key);
c2826d2e 166 return d_stats[key].get();
12c86877
BH
167}
168
abb11ca4 169StatBag::~StatBag() = default;
12c86877 170
4eb26e0f 171template<typename T, typename Comp>
172StatRing<T,Comp>::StatRing(unsigned int size)
12c86877 173{
4eb26e0f 174 d_items.set_capacity(size);
12c86877
BH
175}
176
4eb26e0f 177template<typename T, typename Comp>
178void StatRing<T,Comp>::account(const T& t)
12c86877 179{
4eb26e0f 180 d_items.push_back(t);
181}
12c86877 182
4eb26e0f 183template<typename T, typename Comp>
74e38357 184uint64_t StatRing<T,Comp>::getSize() const
4eb26e0f 185{
4eb26e0f 186 return d_items.capacity();
12c86877 187}
975bee12 188
74e38357
RG
189template<typename T, typename Comp>
190uint64_t StatRing<T,Comp>::getEntriesCount() const
191{
74e38357
RG
192 return d_items.size();
193}
194
4eb26e0f 195template<typename T, typename Comp>
196void StatRing<T,Comp>::resize(unsigned int newsize)
12c86877 197{
4eb26e0f 198 d_items.set_capacity(newsize);
12c86877
BH
199}
200
4eb26e0f 201template<typename T, typename Comp>
202void StatRing<T,Comp>::setHelp(const string &str)
12c86877 203{
42b8372c 204 d_help = str;
12c86877
BH
205}
206
4eb26e0f 207template<typename T, typename Comp>
42b8372c 208string StatRing<T,Comp>::getHelp() const
12c86877
BH
209{
210 return d_help;
211}
212
12c86877 213
4eb26e0f 214template<typename T, typename Comp>
215vector<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
231void 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
237void 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 244void 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
251void 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 258vector<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
277template<typename T, typename Comp>
278void StatRing<T,Comp>::reset()
279{
4eb26e0f 280 d_items.clear();
12c86877
BH
281}
282
283void 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 293void 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 304uint64_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
315uint64_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
326string 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 337vector<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 350bool 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
355void StatBag::blacklist(const string& str) {
356 d_blacklist.insert(str);
357}
358
fadd04cc 359template class StatRing<std::string, CIStringCompare>;
662d5441 360template class StatRing<SComboAddress>;
f2b2f3ad 361template class StatRing<std::tuple<DNSName, QType> >;