]> granicus.if.org Git - icinga2/blob - plugins/thresholds.cpp
Auto-sanitize data before en-/decoding JSON
[icinga2] / plugins / thresholds.cpp
1 /* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */
2
3 #include "plugins/thresholds.hpp"
4 #include <boost/algorithm/string.hpp>
5 #include <boost/lexical_cast.hpp>
6 #include <iostream>
7
8 using namespace boost::algorithm;
9
10 threshold::threshold()
11         : set(false)
12 {}
13
14 threshold::threshold(const double v, const double c, bool l , bool p ) {
15         lower = v;
16         upper = c;
17         legal = l;
18         perc = p;
19 }
20
21 threshold::threshold(const std::wstring& stri)
22 {
23         if (stri.empty())
24                 throw std::invalid_argument("Threshold must not be empty");
25
26         std::wstring str = stri;
27
28         //kill whitespace
29         boost::algorithm::trim(str);
30
31         bool low = (str.at(0) == L'!');
32         if (low)
33                 str = std::wstring(str.begin() + 1, str.end());
34
35         bool pc = false;
36
37         if (str.at(0) == L'[' && str.at(str.length() - 1) == L']') {//is range
38                 str = std::wstring(str.begin() + 1, str.end() - 1);
39                 std::vector<std::wstring> svec;
40                 boost::split(svec, str, boost::is_any_of(L"-"));
41                 if (svec.size() != 2)
42                         throw std::invalid_argument("Threshold range requires two arguments");
43                 std::wstring str1 = svec.at(0), str2 = svec.at(1);
44
45                 if (str1.at(str1.length() - 1) == L'%' && str2.at(str2.length() - 1) == L'%') {
46                         pc = true;
47                         str1 = std::wstring(str1.begin(), str1.end() - 1);
48                         str2 = std::wstring(str2.begin(), str2.end() - 1);
49                 }
50
51                 try {
52                         boost::algorithm::trim(str1);
53                         lower = boost::lexical_cast<DOUBLE>(str1);
54                         boost::algorithm::trim(str2);
55                         upper = boost::lexical_cast<DOUBLE>(str2);
56                         legal = !low; perc = pc; set = true;
57                 } catch (const boost::bad_lexical_cast&) {
58                         throw std::invalid_argument("Unknown Threshold type");
59                 }
60         } else { //not range
61                 if (str.at(str.length() - 1) == L'%') {
62                         pc = true;
63                         str = std::wstring(str.begin(), str.end() - 1);
64                 }
65                 try {
66                         boost::algorithm::trim(str);
67                         lower = upper = boost::lexical_cast<DOUBLE>(str);
68                         legal = !low; perc = pc; set = true;
69                 } catch (const boost::bad_lexical_cast&) {
70                         throw std::invalid_argument("Unknown Threshold type");
71                 }
72         }
73 }
74
75 //return TRUE if the threshold is broken
76 bool threshold::rend(const double val, const double max)
77 {
78         double upperAbs = upper;
79         double lowerAbs = lower;
80
81         if (perc) {
82                 upperAbs = upper / 100.0 * max;
83                 lowerAbs = lower / 100.0 * max;
84         }
85
86         if (!set)
87                 return set;
88         if (lowerAbs == upperAbs)
89                 return val > upperAbs == legal;
90         else
91                 return (val < lowerAbs || upperAbs < val) != legal;
92 }
93
94 //returns a printable string of the threshold
95 std::wstring threshold::pString(const double max)
96 {
97         if (!set)
98                 return L"";
99         //transform percentages to abolute values
100         double lowerAbs = lower;
101         double upperAbs = upper;
102         if (perc) {
103                 lowerAbs = lower / 100.0 * max;
104                 upperAbs = upper / 100.0 * max;
105         }
106
107         std::wstring s, lowerStr = removeZero(lowerAbs),
108                                         upperStr = removeZero(upperAbs);
109
110         if (lower != upper) {
111                 s.append(L"[").append(lowerStr).append(L"-")
112                 .append(upperStr).append(L"]");
113         } else
114                 s.append(lowerStr);
115
116         return s;
117 }
118
119 threshold threshold::toSeconds(const Tunit& fromUnit) {
120         if (!set)
121                 return *this;
122
123         double lowerAbs = lower;
124         double upperAbs = upper;
125
126         switch (fromUnit) {
127         case TunitMS:
128                 lowerAbs = lowerAbs / 1000;
129                 upperAbs = upperAbs / 1000;
130                 break;
131         case TunitS:
132                 lowerAbs = lowerAbs ;
133                 upperAbs = upperAbs ;
134                 break;
135         case TunitM:
136                 lowerAbs = lowerAbs * 60;
137                 upperAbs = upperAbs * 60;
138                 break;
139         case TunitH:
140                 lowerAbs = lowerAbs * 60 * 60;
141                 upperAbs = upperAbs * 60 * 60;
142                 break;
143         }
144
145         return threshold(lowerAbs, upperAbs, legal, perc);
146 }
147
148 std::wstring removeZero(double val)
149 {
150         std::wstring ret = boost::lexical_cast<std::wstring>(val);
151         std::wstring::size_type pos = ret.length();
152         if (ret.find_first_of(L".") == std::string::npos)
153                 return ret;
154         for (std::wstring::reverse_iterator rit = ret.rbegin(); rit != ret.rend(); ++rit) {
155                 if (*rit == L'.') {
156                         return ret.substr(0, pos - 1);
157                 }
158                 if (*rit != L'0') {
159                         return ret.substr(0, pos);
160                 }
161                 pos--;
162         }
163         return L"0";
164 }
165
166 std::vector<std::wstring> splitMultiOptions(const std::wstring& str)
167 {
168         std::vector<std::wstring> sVec;
169         boost::split(sVec, str, boost::is_any_of(L","));
170         return sVec;
171 }
172
173 Bunit parseBUnit(const std::wstring& str)
174 {
175         std::wstring wstr = to_upper_copy(str);
176
177         if (wstr == L"B")
178                 return BunitB;
179         if (wstr == L"KB")
180                 return BunitkB;
181         if (wstr == L"MB")
182                 return BunitMB;
183         if (wstr == L"GB")
184                 return BunitGB;
185         if (wstr == L"TB")
186                 return BunitTB;
187
188         throw std::invalid_argument("Unknown unit type");
189 }
190
191 std::wstring BunitStr(const Bunit& unit)
192 {
193         switch (unit) {
194         case BunitB:
195                 return L"B";
196         case BunitkB:
197                 return L"kB";
198         case BunitMB:
199                 return L"MB";
200         case BunitGB:
201                 return L"GB";
202         case BunitTB:
203                 return L"TB";
204         }
205         return NULL;
206 }
207
208 Tunit parseTUnit(const std::wstring& str) {
209         std::wstring wstr = to_lower_copy(str);
210
211         if (wstr == L"ms")
212                 return TunitMS;
213         if (wstr == L"s")
214                 return TunitS;
215         if (wstr == L"m")
216                 return TunitM;
217         if (wstr == L"h")
218                 return TunitH;
219
220         throw std::invalid_argument("Unknown unit type");
221 }
222
223 std::wstring TunitStr(const Tunit& unit)
224 {
225         switch (unit) {
226         case TunitMS:
227                 return L"ms";
228         case TunitS:
229                 return L"s";
230         case TunitM:
231                 return L"m";
232         case TunitH:
233                 return L"h";
234         }
235         return NULL;
236 }
237
238 void printErrorInfo(unsigned long err)
239 {
240         if (!err)
241                 err = GetLastError();
242         LPWSTR mBuf = NULL;
243         if (!FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
244                 NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&mBuf, 0, NULL))
245                 std::wcout << "Failed to format error message, last error was: " << err << '\n';
246         else {
247                 boost::trim_right(std::wstring(mBuf));
248                 std::wcout << mBuf << std::endl;
249         }
250 }
251
252 std::wstring formatErrorInfo(unsigned long err) {
253         std::wostringstream out;
254         if (!err)
255                 err = GetLastError();
256         LPWSTR mBuf = NULL;
257         if (!FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
258                 NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&mBuf, 0, NULL))
259                 out << "Failed to format error message, last error was: " << err;
260         else {
261                 std::wstring tempOut = std::wstring(mBuf);
262                 boost::trim_right(tempOut);
263                 out << tempOut;
264         }
265
266         return out.str();
267 }
268
269 std::wstring stateToString(const state& state) {
270         switch (state) {
271                 case OK: return L"OK";
272                 case WARNING: return L"WARNING";
273                 case CRITICAL: return L"CRITICAL";
274                 default: return L"UNKNOWN";
275         }
276 }