Coverage Report

Created: 2023-09-25 07:00

/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> >;