]> granicus.if.org Git - icinga2/blob - lib/base/perfdatavalue.cpp
lib->compat->statusdatawriter: fix notifications_enabled
[icinga2] / lib / base / perfdatavalue.cpp
1 /******************************************************************************
2  * Icinga 2                                                                   *
3  * Copyright (C) 2012-2018 Icinga Development Team (https://www.icinga.com/)  *
4  *                                                                            *
5  * This program is free software; you can redistribute it and/or              *
6  * modify it under the terms of the GNU General Public License                *
7  * as published by the Free Software Foundation; either version 2             *
8  * of the License, or (at your option) any later version.                     *
9  *                                                                            *
10  * This program is distributed in the hope that it will be useful,            *
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of             *
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              *
13  * GNU General Public License for more details.                               *
14  *                                                                            *
15  * You should have received a copy of the GNU General Public License          *
16  * along with this program; if not, write to the Free Software Foundation     *
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.             *
18  ******************************************************************************/
19
20 #include "base/perfdatavalue.hpp"
21 #include "base/perfdatavalue-ti.cpp"
22 #include "base/convert.hpp"
23 #include "base/exception.hpp"
24 #include "base/logger.hpp"
25 #include "base/function.hpp"
26
27 using namespace icinga;
28
29 REGISTER_TYPE(PerfdataValue);
30 REGISTER_SCRIPTFUNCTION_NS(System, parse_performance_data, PerfdataValue::Parse, "perfdata");
31
32 PerfdataValue::PerfdataValue(const String& label, double value, bool counter,
33         const String& unit, const Value& warn, const Value& crit, const Value& min,
34         const Value& max)
35 {
36         SetLabel(label, true);
37         SetValue(value, true);
38         SetCounter(counter, true);
39         SetUnit(unit, true);
40         SetWarn(warn, true);
41         SetCrit(crit, true);
42         SetMin(min, true);
43         SetMax(max, true);
44 }
45
46 PerfdataValue::Ptr PerfdataValue::Parse(const String& perfdata)
47 {
48         size_t eqp = perfdata.FindLastOf('=');
49
50         if (eqp == String::NPos)
51                 BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid performance data value: " + perfdata));
52
53         String label = perfdata.SubStr(0, eqp);
54
55         if (label.GetLength() > 2 && label[0] == '\'' && label[label.GetLength() - 1] == '\'')
56                 label = label.SubStr(1, label.GetLength() - 2);
57
58         size_t spq = perfdata.FindFirstOf(' ', eqp);
59
60         if (spq == String::NPos)
61                 spq = perfdata.GetLength();
62
63         String valueStr = perfdata.SubStr(eqp + 1, spq - eqp - 1);
64
65         size_t pos = valueStr.FindFirstNotOf("+-0123456789.e");
66
67         double value = Convert::ToDouble(valueStr.SubStr(0, pos));
68
69         std::vector<String> tokens = valueStr.Split(";");
70
71         bool counter = false;
72         String unit;
73         Value warn, crit, min, max;
74
75         if (pos != String::NPos)
76                 unit = valueStr.SubStr(pos, tokens[0].GetLength() - pos);
77
78         unit = unit.ToLower();
79
80         double base = 1.0;
81
82         if (unit == "us") {
83                 base /= 1000.0 * 1000.0;
84                 unit = "seconds";
85         } else if (unit == "ms") {
86                 base /= 1000.0;
87                 unit = "seconds";
88         } else if (unit == "s") {
89                 unit = "seconds";
90         } else if (unit == "tb") {
91                 base *= 1024.0 * 1024.0 * 1024.0 * 1024.0;
92                 unit = "bytes";
93         } else if (unit == "gb") {
94                 base *= 1024.0 * 1024.0 * 1024.0;
95                 unit = "bytes";
96         } else if (unit == "mb") {
97                 base *= 1024.0 * 1024.0;
98                 unit = "bytes";
99         } else if (unit == "kb") {
100                 base *= 1024.0;
101                 unit = "bytes";
102         } else if (unit == "b") {
103                 unit = "bytes";
104         } else if (unit == "%") {
105                 unit = "percent";
106         } else if (unit == "c") {
107                 counter = true;
108                 unit = "";
109         } else if (unit != "") {
110                 BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid performance data unit: " + unit));
111         }
112
113         warn = ParseWarnCritMinMaxToken(tokens, 1, "warning");
114         crit = ParseWarnCritMinMaxToken(tokens, 2, "critical");
115         min = ParseWarnCritMinMaxToken(tokens, 3, "minimum");
116         max = ParseWarnCritMinMaxToken(tokens, 4, "maximum");
117
118         value = value * base;
119
120         if (!warn.IsEmpty())
121                 warn = warn * base;
122
123         if (!crit.IsEmpty())
124                 crit = crit * base;
125
126         if (!min.IsEmpty())
127                 min = min * base;
128
129         if (!max.IsEmpty())
130                 max = max * base;
131
132         return new PerfdataValue(label, value, counter, unit, warn, crit, min, max);
133 }
134
135 String PerfdataValue::Format() const
136 {
137         std::ostringstream result;
138
139         if (GetLabel().FindFirstOf(" ") != String::NPos)
140                 result << "'" << GetLabel() << "'";
141         else
142                 result << GetLabel();
143
144         result << "=" << Convert::ToString(GetValue());
145
146         String unit;
147
148         if (GetCounter())
149                 unit = "c";
150         else if (GetUnit() == "seconds")
151                 unit = "s";
152         else if (GetUnit() == "percent")
153                 unit = "%";
154         else if (GetUnit() == "bytes")
155                 unit = "B";
156
157         result << unit;
158
159         if (!GetWarn().IsEmpty()) {
160                 result << ";" << Convert::ToString(GetWarn());
161
162                 if (!GetCrit().IsEmpty()) {
163                         result << ";" << Convert::ToString(GetCrit());
164
165                         if (!GetMin().IsEmpty()) {
166                                 result << ";" << Convert::ToString(GetMin());
167
168                                 if (!GetMax().IsEmpty()) {
169                                         result << ";" << Convert::ToString(GetMax());
170                                 }
171                         }
172                 }
173         }
174
175         return result.str();
176 }
177
178 Value PerfdataValue::ParseWarnCritMinMaxToken(const std::vector<String>& tokens, std::vector<String>::size_type index, const String& description)
179 {
180         if (tokens.size() > index && tokens[index] != "U" && tokens[index] != "" && tokens[index].FindFirstNotOf("+-0123456789.e") == String::NPos)
181                 return Convert::ToDouble(tokens[index]);
182         else {
183                 if (tokens.size() > index && tokens[index] != "")
184                         Log(LogDebug, "PerfdataValue")
185                                 << "Ignoring unsupported perfdata " << description << " range, value: '" << tokens[index] << "'.";
186                 return Empty;
187         }
188 }