]> granicus.if.org Git - icinga2/blob - lib/base/perfdatavalue.cpp
Merge pull request #7185 from Icinga/bugfix/gelfwriter-wrong-log-facility
[icinga2] / lib / base / perfdatavalue.cpp
1 /* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */
2
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"
9
10 using namespace icinga;
11
12 REGISTER_TYPE(PerfdataValue);
13 REGISTER_FUNCTION(System, parse_performance_data, PerfdataValue::Parse, "perfdata");
14
15 PerfdataValue::PerfdataValue(const String& label, double value, bool counter,
16         const String& unit, const Value& warn, const Value& crit, const Value& min,
17         const Value& max)
18 {
19         SetLabel(label, true);
20         SetValue(value, true);
21         SetCounter(counter, true);
22         SetUnit(unit, true);
23         SetWarn(warn, true);
24         SetCrit(crit, true);
25         SetMin(min, true);
26         SetMax(max, true);
27 }
28
29 PerfdataValue::Ptr PerfdataValue::Parse(const String& perfdata)
30 {
31         size_t eqp = perfdata.FindLastOf('=');
32
33         if (eqp == String::NPos)
34                 BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid performance data value: " + perfdata));
35
36         String label = perfdata.SubStr(0, eqp);
37
38         if (label.GetLength() > 2 && label[0] == '\'' && label[label.GetLength() - 1] == '\'')
39                 label = label.SubStr(1, label.GetLength() - 2);
40
41         size_t spq = perfdata.FindFirstOf(' ', eqp);
42
43         if (spq == String::NPos)
44                 spq = perfdata.GetLength();
45
46         String valueStr = perfdata.SubStr(eqp + 1, spq - eqp - 1);
47
48         size_t pos = valueStr.FindFirstNotOf("+-0123456789.e");
49
50         double value = Convert::ToDouble(valueStr.SubStr(0, pos));
51
52         std::vector<String> tokens = valueStr.Split(";");
53
54         bool counter = false;
55         String unit;
56         Value warn, crit, min, max;
57
58         if (pos != String::NPos)
59                 unit = valueStr.SubStr(pos, tokens[0].GetLength() - pos);
60
61         unit = unit.ToLower();
62
63         double base = 1.0;
64
65         if (unit == "us") {
66                 base /= 1000.0 * 1000.0;
67                 unit = "seconds";
68         } else if (unit == "ms") {
69                 base /= 1000.0;
70                 unit = "seconds";
71         } else if (unit == "s") {
72                 unit = "seconds";
73         } else if (unit == "tb") {
74                 base *= 1024.0 * 1024.0 * 1024.0 * 1024.0;
75                 unit = "bytes";
76         } else if (unit == "gb") {
77                 base *= 1024.0 * 1024.0 * 1024.0;
78                 unit = "bytes";
79         } else if (unit == "mb") {
80                 base *= 1024.0 * 1024.0;
81                 unit = "bytes";
82         } else if (unit == "kb") {
83                 base *= 1024.0;
84                 unit = "bytes";
85         } else if (unit == "b") {
86                 unit = "bytes";
87         } else if (unit == "%") {
88                 unit = "percent";
89         } else if (unit == "c") {
90                 counter = true;
91                 unit = "";
92         } else if (unit != "") {
93                 BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid performance data unit: " + unit));
94         }
95
96         warn = ParseWarnCritMinMaxToken(tokens, 1, "warning");
97         crit = ParseWarnCritMinMaxToken(tokens, 2, "critical");
98         min = ParseWarnCritMinMaxToken(tokens, 3, "minimum");
99         max = ParseWarnCritMinMaxToken(tokens, 4, "maximum");
100
101         value = value * base;
102
103         if (!warn.IsEmpty())
104                 warn = warn * base;
105
106         if (!crit.IsEmpty())
107                 crit = crit * base;
108
109         if (!min.IsEmpty())
110                 min = min * base;
111
112         if (!max.IsEmpty())
113                 max = max * base;
114
115         return new PerfdataValue(label, value, counter, unit, warn, crit, min, max);
116 }
117
118 String PerfdataValue::Format() const
119 {
120         std::ostringstream result;
121
122         if (GetLabel().FindFirstOf(" ") != String::NPos)
123                 result << "'" << GetLabel() << "'";
124         else
125                 result << GetLabel();
126
127         result << "=" << Convert::ToString(GetValue());
128
129         String unit;
130
131         if (GetCounter())
132                 unit = "c";
133         else if (GetUnit() == "seconds")
134                 unit = "s";
135         else if (GetUnit() == "percent")
136                 unit = "%";
137         else if (GetUnit() == "bytes")
138                 unit = "B";
139
140         result << unit;
141
142         if (!GetWarn().IsEmpty()) {
143                 result << ";" << Convert::ToString(GetWarn());
144
145                 if (!GetCrit().IsEmpty()) {
146                         result << ";" << Convert::ToString(GetCrit());
147
148                         if (!GetMin().IsEmpty()) {
149                                 result << ";" << Convert::ToString(GetMin());
150
151                                 if (!GetMax().IsEmpty()) {
152                                         result << ";" << Convert::ToString(GetMax());
153                                 }
154                         }
155                 }
156         }
157
158         return result.str();
159 }
160
161 Value PerfdataValue::ParseWarnCritMinMaxToken(const std::vector<String>& tokens, std::vector<String>::size_type index, const String& description)
162 {
163         if (tokens.size() > index && tokens[index] != "U" && tokens[index] != "" && tokens[index].FindFirstNotOf("+-0123456789.e") == String::NPos)
164                 return Convert::ToDouble(tokens[index]);
165         else {
166                 if (tokens.size() > index && tokens[index] != "")
167                         Log(LogDebug, "PerfdataValue")
168                                 << "Ignoring unsupported perfdata " << description << " range, value: '" << tokens[index] << "'.";
169                 return Empty;
170         }
171 }