]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/statbag.hh
Merge pull request #14032 from rgacogne/ddist-192-changelog-secpoll
[thirdparty/pdns.git] / pdns / statbag.hh
CommitLineData
12c86877 1/*
12471842
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 */
e8c59f2d 22#pragma once
12c86877 23#include <map>
4eb26e0f 24#include <functional>
12c86877
BH
25#include <string>
26#include <vector>
27#include "lock.hh"
10f4eea8 28#include "namespaces.hh"
4eb26e0f 29#include "iputils.hh"
9f6a31ff 30#include "circular_buffer.hh"
12c86877 31
4eb26e0f 32template<typename T, typename Comp=std::less<T> >
12c86877
BH
33class StatRing
34{
35public:
bb3c3f50 36 StatRing(unsigned int size=10000);
42b8372c
RG
37 StatRing(const StatRing&) = delete;
38 StatRing& operator=(const StatRing&) = delete;
39 StatRing& operator=(StatRing&&) = delete;
40 StatRing(StatRing&&) = default;
6f7df50a 41
4eb26e0f 42 void account(const T &item);
12c86877 43
74e38357
RG
44 uint64_t getSize() const;
45 uint64_t getEntriesCount() const;
6f7df50a 46 void resize(unsigned int newsize);
12c86877
BH
47 void reset();
48 void setHelp(const string &str);
42b8372c 49 string getHelp() const;
4eb26e0f 50
51 vector<pair<T, unsigned int> > get() const;
12c86877 52private:
6f7df50a 53 static bool popisort(const pair<T,int> &a, const pair<T,int> &b)
4eb26e0f 54 {
55 return (a.second > b.second);
56 }
57
58 boost::circular_buffer<T> d_items;
12c86877
BH
59 string d_help;
60};
61
dec69610
MTH
62enum class StatType : uint8_t {
63 counter = 1,
64 gauge = 2,
65};
12c86877
BH
66
67//! use this to gather and query statistics
68class StatBag
69{
c2826d2e 70 map<string, std::unique_ptr<AtomicCounter>> d_stats;
06f46d0a 71 map<string, string> d_keyDescriptions;
dec69610 72 map<string, StatType> d_statTypes;
42b8372c
RG
73 map<string, LockGuarded<StatRing<string, CIStringCompare> > > d_rings;
74 map<string, LockGuarded<StatRing<SComboAddress> > > d_comboRings;
75 map<string, LockGuarded<StatRing<std::tuple<DNSName, QType> > > > d_dnsnameqtyperings;
f4319769 76 typedef std::function<uint64_t(const std::string&)> func_t;
e903706d 77 typedef map<string, func_t> funcstats_t;
78 funcstats_t d_funcstats;
12c86877 79 bool d_doRings;
dbbe10c3 80
f3245c8c 81 std::set<string> d_blacklist;
12c86877 82
74e38357
RG
83 void registerRingStats(const string& name);
84
12c86877
BH
85public:
86 StatBag(); //!< Naked constructor. You need to declare keys before this class becomes useful
87 ~StatBag();
33b222ed 88 void declare(const string &key, const string &descrip="", StatType statType=StatType::counter); //!< Before you can store or access a key, you need to declare it
dec69610 89 void declare(const string &key, const string &descrip, func_t func, StatType statType); //!< Before you can store or access a key, you need to declare it
12c86877
BH
90
91 void declareRing(const string &name, const string &title, unsigned int size=10000);
4eb26e0f 92 void declareComboRing(const string &name, const string &help, unsigned int size=10000);
f2b2f3ad 93 void declareDNSNameQTypeRing(const string &name, const string &help, unsigned int size=10000);
bb3c3f50 94 vector<pair<string, unsigned int> >getRing(const string &name);
12c86877 95 string getRingTitle(const string &name);
4eb26e0f 96 void ringAccount(const char* name, const string &item)
12c86877 97 {
42b8372c
RG
98 if (d_doRings) {
99 auto it = d_rings.find(name);
100 if (it == d_rings.end()) {
e746a2f6 101 throw runtime_error("Attempting to account to nonexistent ring '"+std::string(name)+"'");
42b8372c 102 }
4eb26e0f 103
42b8372c 104 it->second.lock()->account(item);
4eb26e0f 105 }
12c86877 106 }
4eb26e0f 107 void ringAccount(const char* name, const ComboAddress &item)
108 {
42b8372c
RG
109 if (d_doRings) {
110 auto it = d_comboRings.find(name);
111 if (it == d_comboRings.end()) {
e746a2f6 112 throw runtime_error("Attempting to account to nonexistent comboRing '"+std::string(name)+"'");
42b8372c
RG
113 }
114 it->second.lock()->account(item);
4eb26e0f 115 }
116 }
f2b2f3ad
PL
117 void ringAccount(const char* name, const DNSName &dnsname, const QType &qtype)
118 {
42b8372c
RG
119 if (d_doRings) {
120 auto it = d_dnsnameqtyperings.find(name);
121 if (it == d_dnsnameqtyperings.end()) {
e746a2f6 122 throw runtime_error("Attempting to account to nonexistent dnsname+qtype ring '"+std::string(name)+"'");
42b8372c 123 }
0b0882f5 124 it->second.lock()->account(std::tuple(dnsname, qtype));
f2b2f3ad
PL
125 }
126 }
4eb26e0f 127
12c86877
BH
128 void doRings()
129 {
130 d_doRings=true;
131 }
132
42b8372c
RG
133 vector<string>listRings() const;
134 bool ringExists(const string &name) const;
12c86877 135 void resetRing(const string &name);
bb3c3f50 136 void resizeRing(const string &name, unsigned int newsize);
74e38357
RG
137 uint64_t getRingSize(const string &name);
138 uint64_t getRingEntriesCount(const string &name);
12c86877 139
3ef5fc26 140 string directory(const string &prefix = ""); //!< Returns a list of all data stored. If prefix is given, only stats named with this prefix are returned.
12c86877
BH
141 vector<string> getEntries(); //!< returns a vector with datums (items)
142 string getDescrip(const string &item); //!< Returns the description of this datum/item
dec69610 143 StatType getStatType(const string &item); //!< Returns the stats type for the metrics endpoint
12c86877
BH
144 void exists(const string &key); //!< call this function to throw an exception in case a key does not exist
145 inline void deposit(const string &key, int value); //!< increment the statistics behind this key by value amount
146 inline void inc(const string &key); //!< increase this key's value by one
ac0995bb 147 void set(const string &key, unsigned long value); //!< set this key's value
148 unsigned long read(const string &key); //!< read the value behind this key
1566533a 149 AtomicCounter *getPointer(const string &key); //!< get a direct pointer to the value behind a key. Use this for high performance increments
12c86877 150 string getValueStr(const string &key); //!< read a value behind a key, and return it as a string
f3245c8c 151 void blacklist(const string &str);
dbbe10c3
PD
152
153 bool d_allowRedeclare; // only set this true during tests, never in production code
12c86877
BH
154};
155
156inline void StatBag::deposit(const string &key, int value)
157{
12c86877
BH
158 exists(key);
159
160 *d_stats[key]+=value;
12c86877
BH
161}
162
163inline void StatBag::inc(const string &key)
164{
42b8372c 165 deposit(key, 1);
12c86877 166}