/src/pdns/pdns/statbag.hh
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 | | #pragma once |
23 | | #include <map> |
24 | | #include <functional> |
25 | | #include <string> |
26 | | #include <vector> |
27 | | #include "lock.hh" |
28 | | #include "namespaces.hh" |
29 | | #include "iputils.hh" |
30 | | #include "circular_buffer.hh" |
31 | | |
32 | | template<typename T, typename Comp=std::less<T> > |
33 | | class StatRing |
34 | | { |
35 | | public: |
36 | | StatRing(unsigned int size=10000); |
37 | | StatRing(const StatRing&) = delete; |
38 | | StatRing& operator=(const StatRing&) = delete; |
39 | | StatRing& operator=(StatRing&&) = delete; |
40 | 0 | StatRing(StatRing&&) = default; Unexecuted instantiation: StatRing<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, CIStringCompare>::StatRing(StatRing<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, CIStringCompare>&&) Unexecuted instantiation: StatRing<SComboAddress, std::__1::less<SComboAddress> >::StatRing(StatRing<SComboAddress, std::__1::less<SComboAddress> >&&) Unexecuted instantiation: StatRing<std::__1::tuple<DNSName, QType>, std::__1::less<std::__1::tuple<DNSName, QType> > >::StatRing(StatRing<std::__1::tuple<DNSName, QType>, std::__1::less<std::__1::tuple<DNSName, QType> > >&&) |
41 | | |
42 | | void account(const T &item); |
43 | | |
44 | | uint64_t getSize() const; |
45 | | uint64_t getEntriesCount() const; |
46 | | void resize(unsigned int newsize); |
47 | | void reset(); |
48 | | void setHelp(const string &str); |
49 | | string getHelp() const; |
50 | | |
51 | | vector<pair<T, unsigned int> > get() const; |
52 | | private: |
53 | | static bool popisort(const pair<T,int> &a, const pair<T,int> &b) |
54 | 0 | { |
55 | 0 | return (a.second > b.second); |
56 | 0 | } Unexecuted instantiation: StatRing<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, CIStringCompare>::popisort(std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, int> const&, std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, int> const&) Unexecuted instantiation: StatRing<SComboAddress, std::__1::less<SComboAddress> >::popisort(std::__1::pair<SComboAddress, int> const&, std::__1::pair<SComboAddress, int> const&) Unexecuted instantiation: StatRing<std::__1::tuple<DNSName, QType>, std::__1::less<std::__1::tuple<DNSName, QType> > >::popisort(std::__1::pair<std::__1::tuple<DNSName, QType>, int> const&, std::__1::pair<std::__1::tuple<DNSName, QType>, int> const&) |
57 | | |
58 | | boost::circular_buffer<T> d_items; |
59 | | string d_help; |
60 | | }; |
61 | | |
62 | | enum class StatType : uint8_t { |
63 | | counter = 1, |
64 | | gauge = 2, |
65 | | }; |
66 | | |
67 | | //! use this to gather and query statistics |
68 | | class StatBag |
69 | | { |
70 | | map<string, std::unique_ptr<AtomicCounter>> d_stats; |
71 | | map<string, string> d_keyDescriptions; |
72 | | map<string, StatType> d_statTypes; |
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; |
76 | | typedef std::function<uint64_t(const std::string&)> func_t; |
77 | | typedef map<string, func_t> funcstats_t; |
78 | | funcstats_t d_funcstats; |
79 | | bool d_doRings; |
80 | | |
81 | | std::set<string> d_blacklist; |
82 | | |
83 | | void registerRingStats(const string& name); |
84 | | |
85 | | public: |
86 | | StatBag(); //!< Naked constructor. You need to declare keys before this class becomes useful |
87 | | ~StatBag(); |
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 |
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 |
90 | | |
91 | | void declareRing(const string &name, const string &title, unsigned int size=10000); |
92 | | void declareComboRing(const string &name, const string &help, unsigned int size=10000); |
93 | | void declareDNSNameQTypeRing(const string &name, const string &help, unsigned int size=10000); |
94 | | vector<pair<string, unsigned int> >getRing(const string &name); |
95 | | string getRingTitle(const string &name); |
96 | | void ringAccount(const char* name, const string &item) |
97 | 0 | { |
98 | 0 | if (d_doRings) { |
99 | 0 | auto it = d_rings.find(name); |
100 | 0 | if (it == d_rings.end()) { |
101 | 0 | throw runtime_error("Attempting to account to nonexistent ring '"+std::string(name)+"'"); |
102 | 0 | } |
103 | 0 |
|
104 | 0 | it->second.lock()->account(item); |
105 | 0 | } |
106 | 0 | } |
107 | | void ringAccount(const char* name, const ComboAddress &item) |
108 | 0 | { |
109 | 0 | if (d_doRings) { |
110 | 0 | auto it = d_comboRings.find(name); |
111 | 0 | if (it == d_comboRings.end()) { |
112 | 0 | throw runtime_error("Attempting to account to nonexistent comboRing '"+std::string(name)+"'"); |
113 | 0 | } |
114 | 0 | it->second.lock()->account(item); |
115 | 0 | } |
116 | 0 | } |
117 | | void ringAccount(const char* name, const DNSName &dnsname, const QType &qtype) |
118 | 0 | { |
119 | 0 | if (d_doRings) { |
120 | 0 | auto it = d_dnsnameqtyperings.find(name); |
121 | 0 | if (it == d_dnsnameqtyperings.end()) { |
122 | 0 | throw runtime_error("Attempting to account to nonexistent dnsname+qtype ring '"+std::string(name)+"'"); |
123 | 0 | } |
124 | 0 | it->second.lock()->account(std::tuple(dnsname, qtype)); |
125 | 0 | } |
126 | 0 | } |
127 | | |
128 | | void doRings() |
129 | 0 | { |
130 | 0 | d_doRings=true; |
131 | 0 | } |
132 | | |
133 | | vector<string>listRings() const; |
134 | | bool ringExists(const string &name) const; |
135 | | void resetRing(const string &name); |
136 | | void resizeRing(const string &name, unsigned int newsize); |
137 | | uint64_t getRingSize(const string &name); |
138 | | uint64_t getRingEntriesCount(const string &name); |
139 | | |
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. |
141 | | vector<string> getEntries(); //!< returns a vector with datums (items) |
142 | | string getDescrip(const string &item); //!< Returns the description of this datum/item |
143 | | StatType getStatType(const string &item); //!< Returns the stats type for the metrics endpoint |
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 |
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 |
149 | | AtomicCounter *getPointer(const string &key); //!< get a direct pointer to the value behind a key. Use this for high performance increments |
150 | | string getValueStr(const string &key); //!< read a value behind a key, and return it as a string |
151 | | void blacklist(const string &str); |
152 | | |
153 | | bool d_allowRedeclare; // only set this true during tests, never in production code |
154 | | }; |
155 | | |
156 | | inline void StatBag::deposit(const string &key, int value) |
157 | 0 | { |
158 | 0 | exists(key); |
159 | 0 |
|
160 | 0 | *d_stats[key]+=value; |
161 | 0 | } |
162 | | |
163 | | inline void StatBag::inc(const string &key) |
164 | 0 | { |
165 | 0 | deposit(key, 1); |
166 | 0 | } |