1 /******************************************************************************
3 * Copyright (C) 2012-2018 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-ti.cpp"
22 #include "base/convert.hpp"
23 #include "base/exception.hpp"
24 #include "base/logger.hpp"
25 #include "base/function.hpp"
27 using namespace icinga;
29 REGISTER_TYPE(PerfdataValue);
30 REGISTER_SCRIPTFUNCTION_NS(System, parse_performance_data, PerfdataValue::Parse, "perfdata");
32 PerfdataValue::PerfdataValue(const String& label, double value, bool counter,
33 const String& unit, const Value& warn, const Value& crit, const Value& min,
36 SetLabel(label, true);
37 SetValue(value, true);
38 SetCounter(counter, true);
46 PerfdataValue::Ptr PerfdataValue::Parse(const String& perfdata)
48 size_t eqp = perfdata.FindLastOf('=');
50 if (eqp == String::NPos)
51 BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid performance data value: " + perfdata));
53 String label = perfdata.SubStr(0, eqp);
55 if (label.GetLength() > 2 && label[0] == '\'' && label[label.GetLength() - 1] == '\'')
56 label = label.SubStr(1, label.GetLength() - 2);
58 size_t spq = perfdata.FindFirstOf(' ', eqp);
60 if (spq == String::NPos)
61 spq = perfdata.GetLength();
63 String valueStr = perfdata.SubStr(eqp + 1, spq - eqp - 1);
65 size_t pos = valueStr.FindFirstNotOf("+-0123456789.e");
67 double value = Convert::ToDouble(valueStr.SubStr(0, pos));
69 std::vector<String> tokens = valueStr.Split(";");
73 Value warn, crit, min, max;
75 if (pos != String::NPos)
76 unit = valueStr.SubStr(pos, tokens[0].GetLength() - pos);
78 unit = unit.ToLower();
83 base /= 1000.0 * 1000.0;
85 } else if (unit == "ms") {
88 } else if (unit == "s") {
90 } else if (unit == "tb") {
91 base *= 1024.0 * 1024.0 * 1024.0 * 1024.0;
93 } else if (unit == "gb") {
94 base *= 1024.0 * 1024.0 * 1024.0;
96 } else if (unit == "mb") {
97 base *= 1024.0 * 1024.0;
99 } else if (unit == "kb") {
102 } else if (unit == "b") {
104 } else if (unit == "%") {
106 } else if (unit == "c") {
109 } else if (unit != "") {
110 BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid performance data unit: " + unit));
113 warn = ParseWarnCritMinMaxToken(tokens, 1, "warning");
114 crit = ParseWarnCritMinMaxToken(tokens, 2, "critical");
115 min = ParseWarnCritMinMaxToken(tokens, 3, "minimum");
116 max = ParseWarnCritMinMaxToken(tokens, 4, "maximum");
118 value = value * base;
132 return new PerfdataValue(label, value, counter, unit, warn, crit, min, max);
135 String PerfdataValue::Format() const
137 std::ostringstream result;
139 if (GetLabel().FindFirstOf(" ") != String::NPos)
140 result << "'" << GetLabel() << "'";
142 result << GetLabel();
144 result << "=" << Convert::ToString(GetValue());
150 else if (GetUnit() == "seconds")
152 else if (GetUnit() == "percent")
154 else if (GetUnit() == "bytes")
159 if (!GetWarn().IsEmpty()) {
160 result << ";" << Convert::ToString(GetWarn());
162 if (!GetCrit().IsEmpty()) {
163 result << ";" << Convert::ToString(GetCrit());
165 if (!GetMin().IsEmpty()) {
166 result << ";" << Convert::ToString(GetMin());
168 if (!GetMax().IsEmpty()) {
169 result << ";" << Convert::ToString(GetMax());
178 Value PerfdataValue::ParseWarnCritMinMaxToken(const std::vector<String>& tokens, std::vector<String>::size_type index, const String& description)
180 if (tokens.size() > index && tokens[index] != "U" && tokens[index] != "" && tokens[index].FindFirstNotOf("+-0123456789.e") == String::NPos)
181 return Convert::ToDouble(tokens[index]);
183 if (tokens.size() > index && tokens[index] != "")
184 Log(LogDebug, "PerfdataValue")
185 << "Ignoring unsupported perfdata " << description << " range, value: '" << tokens[index] << "'.";