1 /* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */
3 #include "base/perfdatavalue.hpp"
4 #include "base/perfdatavalue-ti.cpp"
5 #include "base/convert.hpp"
6 #include "base/exception.hpp"
7 #include "base/logger.hpp"
8 #include "base/function.hpp"
10 using namespace icinga;
12 REGISTER_TYPE(PerfdataValue);
13 REGISTER_FUNCTION(System, parse_performance_data, PerfdataValue::Parse, "perfdata");
15 PerfdataValue::PerfdataValue(const String& label, double value, bool counter,
16 const String& unit, const Value& warn, const Value& crit, const Value& min,
19 SetLabel(label, true);
20 SetValue(value, true);
21 SetCounter(counter, true);
29 PerfdataValue::Ptr PerfdataValue::Parse(const String& perfdata)
31 size_t eqp = perfdata.FindLastOf('=');
33 if (eqp == String::NPos)
34 BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid performance data value: " + perfdata));
36 String label = perfdata.SubStr(0, eqp);
38 if (label.GetLength() > 2 && label[0] == '\'' && label[label.GetLength() - 1] == '\'')
39 label = label.SubStr(1, label.GetLength() - 2);
41 size_t spq = perfdata.FindFirstOf(' ', eqp);
43 if (spq == String::NPos)
44 spq = perfdata.GetLength();
46 String valueStr = perfdata.SubStr(eqp + 1, spq - eqp - 1);
48 size_t pos = valueStr.FindFirstNotOf("+-0123456789.e");
50 double value = Convert::ToDouble(valueStr.SubStr(0, pos));
52 std::vector<String> tokens = valueStr.Split(";");
56 Value warn, crit, min, max;
58 if (pos != String::NPos)
59 unit = valueStr.SubStr(pos, tokens[0].GetLength() - pos);
61 unit = unit.ToLower();
66 base /= 1000.0 * 1000.0;
68 } else if (unit == "ms") {
71 } else if (unit == "s") {
73 } else if (unit == "tb") {
74 base *= 1024.0 * 1024.0 * 1024.0 * 1024.0;
76 } else if (unit == "gb") {
77 base *= 1024.0 * 1024.0 * 1024.0;
79 } else if (unit == "mb") {
80 base *= 1024.0 * 1024.0;
82 } else if (unit == "kb") {
85 } else if (unit == "b") {
87 } else if (unit == "%") {
89 } else if (unit == "c") {
92 } else if (unit != "") {
93 BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid performance data unit: " + unit));
96 warn = ParseWarnCritMinMaxToken(tokens, 1, "warning");
97 crit = ParseWarnCritMinMaxToken(tokens, 2, "critical");
98 min = ParseWarnCritMinMaxToken(tokens, 3, "minimum");
99 max = ParseWarnCritMinMaxToken(tokens, 4, "maximum");
101 value = value * base;
115 return new PerfdataValue(label, value, counter, unit, warn, crit, min, max);
118 String PerfdataValue::Format() const
120 std::ostringstream result;
122 if (GetLabel().FindFirstOf(" ") != String::NPos)
123 result << "'" << GetLabel() << "'";
125 result << GetLabel();
127 result << "=" << Convert::ToString(GetValue());
133 else if (GetUnit() == "seconds")
135 else if (GetUnit() == "percent")
137 else if (GetUnit() == "bytes")
142 if (!GetWarn().IsEmpty()) {
143 result << ";" << Convert::ToString(GetWarn());
145 if (!GetCrit().IsEmpty()) {
146 result << ";" << Convert::ToString(GetCrit());
148 if (!GetMin().IsEmpty()) {
149 result << ";" << Convert::ToString(GetMin());
151 if (!GetMax().IsEmpty()) {
152 result << ";" << Convert::ToString(GetMax());
161 Value PerfdataValue::ParseWarnCritMinMaxToken(const std::vector<String>& tokens, std::vector<String>::size_type index, const String& description)
163 if (tokens.size() > index && tokens[index] != "U" && tokens[index] != "" && tokens[index].FindFirstNotOf("+-0123456789.e") == String::NPos)
164 return Convert::ToDouble(tokens[index]);
166 if (tokens.size() > index && tokens[index] != "")
167 Log(LogDebug, "PerfdataValue")
168 << "Ignoring unsupported perfdata " << description << " range, value: '" << tokens[index] << "'.";