1 /******************************************************************************
3 * Copyright (C) 2012-2017 Icinga Development Team (https://www.icinga.com/) *
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. *
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. *
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 ******************************************************************************/
20 #include "base/perfdatavalue.hpp"
21 #include "base/perfdatavalue.tcpp"
22 #include "base/convert.hpp"
23 #include "base/exception.hpp"
24 #include "base/logger.hpp"
25 #include "base/function.hpp"
26 #include <boost/algorithm/string/case_conv.hpp>
27 #include <boost/algorithm/string/split.hpp>
28 #include <boost/algorithm/string/classification.hpp>
30 using namespace icinga;
32 REGISTER_TYPE(PerfdataValue);
33 REGISTER_SCRIPTFUNCTION_NS(System, parse_performance_data, PerfdataValue::Parse, "perfdata");
35 PerfdataValue::PerfdataValue(void)
38 PerfdataValue::PerfdataValue(String label, double value, bool counter,
39 const String& unit, const Value& warn, const Value& crit, const Value& min,
42 SetLabel(label, true);
43 SetValue(value, true);
44 SetCounter(counter, true);
52 PerfdataValue::Ptr PerfdataValue::Parse(const String& perfdata)
54 size_t eqp = perfdata.FindLastOf('=');
56 if (eqp == String::NPos)
57 BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid performance data value: " + perfdata));
59 String label = perfdata.SubStr(0, eqp);
61 if (label.GetLength() > 2 && label[0] == '\'' && label[label.GetLength() - 1] == '\'')
62 label = label.SubStr(1, label.GetLength() - 2);
64 size_t spq = perfdata.FindFirstOf(' ', eqp);
66 if (spq == String::NPos)
67 spq = perfdata.GetLength();
69 String valueStr = perfdata.SubStr(eqp + 1, spq - eqp - 1);
71 size_t pos = valueStr.FindFirstNotOf("+-0123456789.e");
73 double value = Convert::ToDouble(valueStr.SubStr(0, pos));
75 std::vector<String> tokens;
76 boost::algorithm::split(tokens, valueStr, boost::is_any_of(";"));
80 Value warn, crit, min, max;
82 if (pos != String::NPos)
83 unit = valueStr.SubStr(pos, tokens[0].GetLength() - pos);
85 boost::algorithm::to_lower(unit);
90 base /= 1000.0 * 1000.0;
92 } else if (unit == "ms") {
95 } else if (unit == "s") {
97 } else if (unit == "tb") {
98 base *= 1024.0 * 1024.0 * 1024.0 * 1024.0;
100 } else if (unit == "gb") {
101 base *= 1024.0 * 1024.0 * 1024.0;
103 } else if (unit == "mb") {
104 base *= 1024.0 * 1024.0;
106 } else if (unit == "kb") {
109 } else if (unit == "b") {
111 } else if (unit == "%") {
113 } else if (unit == "c") {
116 } else if (unit != "") {
117 BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid performance data unit: " + unit));
120 warn = ParseWarnCritMinMaxToken(tokens, 1, "warning");
121 crit = ParseWarnCritMinMaxToken(tokens, 2, "critical");
122 min = ParseWarnCritMinMaxToken(tokens, 3, "minimum");
123 max = ParseWarnCritMinMaxToken(tokens, 4, "maximum");
125 value = value * base;
139 return new PerfdataValue(label, value, counter, unit, warn, crit, min, max);
142 String PerfdataValue::Format(void) const
144 std::ostringstream result;
146 if (GetLabel().FindFirstOf(" ") != String::NPos)
147 result << "'" << GetLabel() << "'";
149 result << GetLabel();
151 result << "=" << Convert::ToString(GetValue());
157 else if (GetUnit() == "seconds")
159 else if (GetUnit() == "percent")
161 else if (GetUnit() == "bytes")
166 if (!GetWarn().IsEmpty()) {
167 result << ";" << Convert::ToString(GetWarn());
169 if (!GetCrit().IsEmpty()) {
170 result << ";" << Convert::ToString(GetCrit());
172 if (!GetMin().IsEmpty()) {
173 result << ";" << Convert::ToString(GetMin());
175 if (!GetMax().IsEmpty()) {
176 result << ";" << Convert::ToString(GetMax());
185 Value PerfdataValue::ParseWarnCritMinMaxToken(const std::vector<String>& tokens, std::vector<String>::size_type index, const String& description)
187 if (tokens.size() > index && tokens[index] != "U" && tokens[index] != "" && tokens[index].FindFirstNotOf("+-0123456789.e") == String::NPos)
188 return Convert::ToDouble(tokens[index]);
190 if (tokens.size() > index && tokens[index] != "")
191 Log(LogDebug, "PerfdataValue")
192 << "Ignoring unsupported perfdata " << description << " range, value: '" << tokens[index] << "'.";