]> granicus.if.org Git - icinga2/commitdiff
Use PluginUtility::{Parse,Format}Perfdata for check results.
authorGunnar Beutner <gunnar.beutner@netways.de>
Thu, 7 Nov 2013 13:38:37 +0000 (14:38 +0100)
committerGunnar Beutner <gunnar.beutner@netways.de>
Thu, 7 Nov 2013 15:07:52 +0000 (16:07 +0100)
Refs #2710

components/perfdata/graphitewriter.cpp
components/perfdata/graphitewriter.h
lib/icinga/compatutility.cpp
lib/icinga/host.cpp
lib/icinga/pluginutility.cpp
lib/icinga/service.cpp
lib/methods/nullchecktask.cpp
lib/methods/randomchecktask.cpp

index f5284888d4977e8dd5d92f9e884cd575b7916ab0..4a101223f05ae263f613933ee9a860356c765796 100644 (file)
@@ -22,6 +22,7 @@
 #include "icinga/macroprocessor.h"
 #include "icinga/icingaapplication.h"
 #include "icinga/compatutility.h"
+#include "icinga/perfdatavalue.h"
 #include "base/tcpsocket.h"
 #include "base/dynamictype.h"
 #include "base/objectlock.h"
@@ -82,122 +83,36 @@ void GraphiteWriter::CheckResultHandler(const Service::Ptr& service, const Dicti
        if (!IcingaApplication::GetInstance()->GetEnablePerfdata() || !service->GetEnablePerfdata())
                return;
 
-       Host::Ptr host = service->GetHost();
+       /* basic metrics */
+       SendMetric(service, "current_attempt", service->GetCheckAttempt());
+       SendMetric(service, "max_check_attempts", service->GetMaxCheckAttempts());
+       SendMetric(service, "state_type", service->GetStateType());
+       SendMetric(service, "state", service->GetState());
+       SendMetric(service, "latency", Service::CalculateLatency(cr));
+       SendMetric(service, "execution_time", Service::CalculateExecutionTime(cr));
+
+       Value pdv = cr->Get("performance_data");
 
-       if (!host)
+       if (!pdv.IsObjectType<Dictionary>())
                return;
 
-       /* service metrics */
-       std::vector<String> metrics;
-       String metricName;
-       Value metricValue;
+       Dictionary::Ptr perfdata = pdv;
 
-       /* basic metrics */
-       AddServiceMetric(metrics, service, "current_attempt", service->GetCheckAttempt());
-       AddServiceMetric(metrics, service, "max_check_attempts", service->GetMaxCheckAttempts());
-       AddServiceMetric(metrics, service, "state_type", service->GetStateType());
-       AddServiceMetric(metrics, service, "state", service->GetState());
-       AddServiceMetric(metrics, service, "latency", Service::CalculateLatency(cr));
-       AddServiceMetric(metrics, service, "execution_time", Service::CalculateExecutionTime(cr));
-
-       /* performance data metrics */
-       String perfdata = CompatUtility::GetCheckResultPerfdata(cr);
-
-       if (!perfdata.IsEmpty()) {
-               perfdata.Trim();
-
-               Log(LogDebug, "perfdata", "GraphiteWriter: Processing perfdata: '" + perfdata + "'.");
-
-               /*
-                * 'foo bar'=0;;; baz=0.0;;;
-                * 'label'=value[UOM];[warn];[crit];[min];[max]
-               */
-               std::vector<String> tokens;
-               boost::algorithm::split(tokens, perfdata, boost::is_any_of(" "));
-
-               /* TODO deal with white spaces in single quoted labels: 'foo bar'=0;;; 'baz'=1.0;;;
-                * 1. find first ', find second ' -> if no '=' in between, this is a label
-                * 2. two single quotes define an escaped single quite
-                * 3. warn/crit/min/max may be null and semicolon delimiter omitted
-                * https://www.nagios-plugins.org/doc/guidelines.html#AEN200
-                */
-               BOOST_FOREACH(const String& token, tokens) {
-                       String metricKeyVal = token;
-                       metricKeyVal.Trim();
-
-                       std::vector<String> key_val;
-                       boost::algorithm::split(key_val, metricKeyVal, boost::is_any_of("="));
-
-                       if (key_val.size() == 0) {
-                               Log(LogWarning, "perfdata", "GraphiteWriter: Invalid performance data. No assignment operator found in :'" + metricKeyVal + "'.");
-                               return;
-                       }
-
-                       String metricName = key_val[0];
-                       metricName.Trim();
-
-                       if (key_val.size() == 1) {
-                               Log(LogWarning, "perfdata", "GraphiteWriter: Invalid performance data: '" + metricKeyVal + "' with key: '" + metricName + "'.");
-                               return;
-                       }
-
-                       String metricValues = key_val[1];
-                       metricValues.Trim();
-
-                       std::vector<String> perfdata_values;
-                       boost::algorithm::split(perfdata_values, metricValues, boost::is_any_of(";"));
-
-                       if (perfdata_values.size() == 0) {
-                               Log(LogWarning, "perfdata", "GraphiteWriter: Invalid performance data: '" + metricKeyVal +
-                                   "' with key: '" + metricName + "' and values: '" + metricValues + "'.");
-                               return;
-                       }
-
-                       String metricValue = perfdata_values[0];
-
-                       metricValue.Trim();
-                       Log(LogDebug, "perfdata", "GraphiteWriter: Trimmed metric value: '" + metricValue + "'.");
-
-                       /* extract raw value (digit number digit as double) and uom
-                        * http://en.highscore.de/cpp/boost/stringhandling.html
-                        */
-                       String metricValueRaw = boost::algorithm::trim_right_copy_if(metricValue, (!boost::algorithm::is_digit() && !boost::algorithm::is_any_of(".,")));
-                       String metricValueUom = boost::algorithm::trim_left_copy_if(metricValue, (boost::algorithm::is_digit() || boost::algorithm::is_any_of(".,")));
-
-                       Log(LogDebug, "perfdata", "GraphiteWriter: Raw metric value: '" + metricValueRaw + "' with UOM: '" + metricValueUom + "'.");
-
-                       /* TODO: Normalize raw value based on UOM
-                        * a. empty - assume a number
-                        * b. 's' - seconds (us, ms)
-                        * c. '%' - percentage
-                        * d. 'B' - bytes (KB, MB, GB, TB)
-                        * e. 'c' - continous counter (snmp)
-                        */
-
-                       /* //TODO: Figure out how graphite handles warn/crit/min/max
-                       String metricValueWarn, metricValueCrit, metricValueMin, metricValueMax;
-
-                       if (perfdata_values.size() > 1)
-                               metricValueWarn = perfdata_values[1];
-                       if (perfdata_values.size() > 2)
-                               metricValueCrit = perfdata_values[2];
-                       if (perfdata_values.size() > 3)
-                               metricValueMin = perfdata_values[3];
-                       if (perfdata_values.size() > 4)
-                               metricValueMax = perfdata_values[4];
-                       */
-
-                       /* sanitize invalid metric characters */
-                       SanitizeMetric(metricName);
-
-                       AddServiceMetric(metrics, service, metricName, metricValueRaw);
-               }
-       }
+       String key;
+       Value value;
+       BOOST_FOREACH(boost::tie(key, value), perfdata) {
+               double valueNum;
 
-       SendMetrics(metrics);
+               if (!value.IsObjectType<PerfdataValue>())
+                       valueNum = value;
+               else
+                       valueNum = static_cast<PerfdataValue::Ptr>(value)->GetValue();
+
+               SendMetric(service, key, valueNum);
+       }
 }
 
-void GraphiteWriter::AddServiceMetric(std::vector<String>& metrics, const Service::Ptr& service, const String& name, const Value& value)
+void GraphiteWriter::SendMetric(const Service::Ptr& service, const String& name, double value)
 {
        /* TODO: sanitize host and service names */
        String hostName = service->GetHost()->GetName();
@@ -211,33 +126,22 @@ void GraphiteWriter::AddServiceMetric(std::vector<String>& metrics, const Servic
 
        String metric = graphitePrefix + "." + metricPrefix + "." + name + " " + Convert::ToString(value) + " " + Convert::ToString(static_cast<long>(Utility::GetTime())) + "\n";
        Log(LogDebug, "perfdata", "GraphiteWriter: Add to metric list:'" + metric + "'.");
-       metrics.push_back(metric);
-}
 
-void GraphiteWriter::SendMetrics(const std::vector<String>& metrics)
-{
-       BOOST_FOREACH(const String& metric, metrics) {
-               if (metric.IsEmpty())
-                       continue;
+       ObjectLock olock(this);
 
-               Log(LogDebug, "perfdata", "GraphiteWriter: Sending metric '" + metric + "'.");
-
-               ObjectLock olock(this);
-
-               if (!m_Stream)
-                       return;
+       if (!m_Stream)
+               return;
 
-               try {
-                       m_Stream->Write(metric.CStr(), metric.GetLength());
-               } catch (const std::exception& ex) {
-                       std::ostringstream msgbuf;
-                       msgbuf << "Exception thrown while writing to the Graphite socket: " << std::endl
-                               << boost::diagnostic_information(ex);
+       try {
+               m_Stream->Write(metric.CStr(), metric.GetLength());
+       } catch (const std::exception& ex) {
+               std::ostringstream msgbuf;
+               msgbuf << "Exception thrown while writing to the Graphite socket: " << std::endl
+                      << boost::diagnostic_information(ex);
 
-                       Log(LogCritical, "base", msgbuf.str());
+               Log(LogCritical, "base", msgbuf.str());
 
-                       m_Stream.reset();
-               }
+               m_Stream.reset();
        }
 }
 
@@ -249,4 +153,3 @@ void GraphiteWriter::SanitizeMetric(String& str)
        boost::replace_all(str, "\\", "_");
        boost::replace_all(str, "/", "_");
 }
-
index b99736338009c46a897444c257a8f265af564a4f..133790fd155d270a73743c49a8a08c07fe4231ba 100644 (file)
@@ -50,10 +50,9 @@ private:
         Timer::Ptr m_ReconnectTimer;
 
        void CheckResultHandler(const Service::Ptr& service, const Dictionary::Ptr& cr);
-        static void AddServiceMetric(std::vector<String>& metrics, const Service::Ptr& service, const String& name, const Value& value);
-        void SendMetrics(const std::vector<String>& metrics);
+        void SendMetric(const Service::Ptr& service, const String& name, double value);
         static void SanitizeMetric(String& str);
-        
+
         void ReconnectTimerHandler(void);
 };
 
index 511701756a9bcc1734933c0195fe222feb9952fa..de26f8c914444601c06ab4a01367dc1647edb3a1 100644 (file)
  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.             *
  ******************************************************************************/
 
-#include "base/convert.h"
 #include "icinga/compatutility.h"
 #include "icinga/checkcommand.h"
 #include "icinga/eventcommand.h"
+#include "icinga/pluginutility.h"
 #include "base/dynamictype.h"
 #include "base/objectlock.h"
 #include "base/debug.h"
+#include "base/convert.h"
 #include <boost/foreach.hpp>
 #include <boost/tuple/tuple.hpp>
 #include <boost/algorithm/string/replace.hpp>
@@ -556,12 +557,10 @@ Dictionary::Ptr CompatUtility::GetCheckResultOutput(const Dictionary::Ptr& cr)
 String CompatUtility::GetCheckResultPerfdata(const Dictionary::Ptr& cr)
 {
        if (!cr)
-               return Empty;
-
-       String perfdata = EscapeString(cr->Get("performance_data_raw"));
-       perfdata.Trim();
+               return String();
 
-       return perfdata;
+       Dictionary::Ptr perfdata = cr->Get("performance_data");
+       return PluginUtility::FormatPerfdata(perfdata);
 }
 
 String CompatUtility::EscapeString(const String& str)
index 13e6d82cf3e6efd61a925c0b0788795105d2d0c2..7dbc04cfe0b749fdc249f78c99d01f26f0c8b9ef 100644 (file)
@@ -21,6 +21,7 @@
 #include "icinga/service.h"
 #include "icinga/hostgroup.h"
 #include "icinga/icingaapplication.h"
+#include "icinga/pluginutility.h"
 #include "base/dynamictype.h"
 #include "base/objectlock.h"
 #include "base/logger_fwd.h"
@@ -619,7 +620,7 @@ bool Host::ResolveMacro(const String& macro, const Dictionary::Ptr&, String *res
                        *result = hccr->Get("output");
                        return true;
                } else if (macro == "HOSTPERFDATA") {
-                       *result = hccr->Get("performance_data_raw");
+                       *result = PluginUtility::FormatPerfdata(hccr->Get("performance_data"));
                        return true;
                } else if (macro == "LASTHOSTCHECK") {
                        *result = Convert::ToString((long)hccr->Get("schedule_start"));
index 5589870e53f08cc6361bc0033db07e23eed518e7..4e9af85e9769c32b793872383393084d0c5615e9 100644 (file)
@@ -76,7 +76,7 @@ Dictionary::Ptr PluginUtility::ParseCheckOutput(const String& output)
        }
 
        result->Set("output", text);
-       result->Set("performance_data_raw", perfdata);
+       result->Set("performance_data", ParsePerfdata(perfdata));
 
        return result;
 }
index 38d9848f9b5509b28e1c0106921a6ce9a0b18c90..484c9abdafbe4185428d67d1d4d0dc100a2a3b58 100644 (file)
@@ -22,6 +22,7 @@
 #include "icinga/checkcommand.h"
 #include "icinga/icingaapplication.h"
 #include "icinga/macroprocessor.h"
+#include "icinga/pluginutility.h"
 #include "config/configitembuilder.h"
 #include "base/dynamictype.h"
 #include "base/objectlock.h"
@@ -393,7 +394,7 @@ bool Service::ResolveMacro(const String& macro, const Dictionary::Ptr& cr, Strin
                        *result = cr->Get("output");
                        return true;
                } else if (macro == "SERVICEPERFDATA") {
-                       *result = cr->Get("performance_data_raw");
+                       *result = PluginUtility::FormatPerfdata(cr->Get("performance_data"));
                        return true;
                } else if (macro == "LASTSERVICECHECK") {
                        *result = Convert::ToString((long)cr->Get("execution_end"));
index 42368c572d6fc902d80eec4a0855bb40398e5437..01e80fdcadf89b4a8967cd5468c8e5ba42899b77 100644 (file)
@@ -39,11 +39,13 @@ Dictionary::Ptr NullCheckTask::ScriptFunc(const Service::Ptr&)
 
        String output = "Hello from ";
        output += name;
-       String perfdata = "time=" + Convert::ToString(static_cast<double>(Utility::GetTime()));
+
+       Dictionary::Ptr perfdata = make_shared<Dictionary>();
+       perfdata->Set("time", Utility::GetTime());
 
        Dictionary::Ptr cr = make_shared<Dictionary>();
        cr->Set("output", output);
-       cr->Set("performance_data_raw", perfdata);
+       cr->Set("performance_data", perfdata);
        cr->Set("state", StateOK);
 
        return cr;
index 9c6f9b8feb8cf5a1633b7e26a40f17803401abd8..2ca8c4b70eb76a3bc55a6f28ec84a67f994c9eac 100644 (file)
@@ -39,11 +39,13 @@ Dictionary::Ptr RandomCheckTask::ScriptFunc(const Service::Ptr&)
 
        String output = "Hello from ";
        output += name;
-       String perfdata = "time=" + Convert::ToString(static_cast<double>(Utility::GetTime()));
+
+       Dictionary::Ptr perfdata = make_shared<Dictionary>();
+       perfdata->Set("time", Utility::GetTime());
 
        Dictionary::Ptr cr = make_shared<Dictionary>();
        cr->Set("output", output);
-       cr->Set("performance_data_raw", perfdata);
+       cr->Set("performance_data", perfdata);
        cr->Set("state", static_cast<ServiceState>(Utility::Random() % 4));
 
        return cr;