]> git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/statbag.hh
Merge pull request #14021 from Habbie/auth-lua-join-whitespace
[thirdparty/pdns.git] / pdns / statbag.hh
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 #ifndef STATBAG_HH
23 #define STATBAG_HH
24 #include <pthread.h>
25 #include <map>
26 #include <functional>
27 #include <string>
28 #include <vector>
29 #include "lock.hh"
30 #include "namespaces.hh"
31 #include "iputils.hh"
32 #include "circular_buffer.hh"
33
34
35
36 template<typename T, typename Comp=std::less<T> >
37 class StatRing
38 {
39 public:
40 StatRing(unsigned int size=10000);
41 void account(const T &item);
42
43 unsigned int getSize();
44 void resize(unsigned int newsize);
45 void reset();
46 void setHelp(const string &str);
47 string getHelp();
48
49 vector<pair<T, unsigned int> > get() const;
50 private:
51 static bool popisort(const pair<T,int> &a, const pair<T,int> &b)
52 {
53 return (a.second > b.second);
54 }
55
56 boost::circular_buffer<T> d_items;
57 mutable pthread_mutex_t d_lock;
58 string d_help;
59 };
60
61
62 //! use this to gather and query statistics
63 class StatBag
64 {
65 map<string, AtomicCounter *> d_stats;
66 map<string, string> d_keyDescrips;
67 map<string,StatRing<string, CIStringCompare> >d_rings;
68 map<string,StatRing<SComboAddress> >d_comborings;
69 map<string,StatRing<std::tuple<DNSName, QType> > >d_dnsnameqtyperings;
70 typedef boost::function<uint64_t(const std::string&)> func_t;
71 typedef map<string, func_t> funcstats_t;
72 funcstats_t d_funcstats;
73 bool d_doRings;
74 std::set<string> d_blacklist;
75
76 public:
77 StatBag(); //!< Naked constructor. You need to declare keys before this class becomes useful
78 ~StatBag();
79 void declare(const string &key, const string &descrip=""); //!< Before you can store or access a key, you need to declare it
80 void declare(const string &key, const string &descrip, func_t func); //!< Before you can store or access a key, you need to declare it
81
82 void declareRing(const string &name, const string &title, unsigned int size=10000);
83 void declareComboRing(const string &name, const string &help, unsigned int size=10000);
84 void declareDNSNameQTypeRing(const string &name, const string &help, unsigned int size=10000);
85 vector<pair<string, unsigned int> >getRing(const string &name);
86 string getRingTitle(const string &name);
87 void ringAccount(const char* name, const string &item)
88 {
89 if(d_doRings) {
90 if(!d_rings.count(name))
91 throw runtime_error("Attempting to account to non-existent ring '"+std::string(name)+"'");
92
93 d_rings[name].account(item);
94 }
95 }
96 void ringAccount(const char* name, const ComboAddress &item)
97 {
98 if(d_doRings) {
99 if(!d_comborings.count(name))
100 throw runtime_error("Attempting to account to non-existent comboring '"+std::string(name)+"'");
101 d_comborings[name].account(item);
102 }
103 }
104 void ringAccount(const char* name, const DNSName &dnsname, const QType &qtype)
105 {
106 if(d_doRings) {
107 if(!d_dnsnameqtyperings.count(name))
108 throw runtime_error("Attempting to account to non-existent dnsname+qtype ring '"+std::string(name)+"'");
109 d_dnsnameqtyperings[name].account(std::make_tuple(dnsname, qtype));
110 }
111 }
112
113 void doRings()
114 {
115 d_doRings=true;
116 }
117
118 vector<string>listRings();
119 bool ringExists(const string &name);
120 void resetRing(const string &name);
121 void resizeRing(const string &name, unsigned int newsize);
122 unsigned int getRingSize(const string &name);
123
124 string directory(); //!< Returns a list of all data stored
125 vector<string> getEntries(); //!< returns a vector with datums (items)
126 string getDescrip(const string &item); //!< Returns the description of this datum/item
127 void exists(const string &key); //!< call this function to throw an exception in case a key does not exist
128 inline void deposit(const string &key, int value); //!< increment the statistics behind this key by value amount
129 inline void inc(const string &key); //!< increase this key's value by one
130 void set(const string &key, unsigned long value); //!< set this key's value
131 unsigned long read(const string &key); //!< read the value behind this key
132 unsigned long readZero(const string &key); //!< read the value behind this key, and zero it afterwards
133 AtomicCounter *getPointer(const string &key); //!< get a direct pointer to the value behind a key. Use this for high performance increments
134 string getValueStr(const string &key); //!< read a value behind a key, and return it as a string
135 string getValueStrZero(const string &key); //!< read a value behind a key, and return it as a string, and zero afterwards
136 void blacklist(const string &str);
137 };
138
139 inline void StatBag::deposit(const string &key, int value)
140 {
141 exists(key);
142
143 *d_stats[key]+=value;
144 }
145
146 inline void StatBag::inc(const string &key)
147 {
148 deposit(key,1);
149 }
150
151
152 #endif /* STATBAG_HH */