]> granicus.if.org Git - icinga2/commitdiff
Add service metadata to InfluxDB Writer
authorSimon Murray <spjmurray@yahoo.co.uk>
Wed, 8 Jun 2016 10:09:21 +0000 (11:09 +0100)
committerGunnar Beutner <gunnar.beutner@netways.de>
Wed, 8 Jun 2016 11:23:52 +0000 (13:23 +0200)
Adds a new configuration variable in keeping with the graphite writer
which defaults to false to save network bandwidth.  All metrics currently
supported by graphite are now available to InfluxDB.  I added in some
formatting functions, to handle integers and booleans as we know and
control their types, and the supporting regexes in the sanity checker.

Updating to InfluxDB 0.13.X started giving 400 errors due to the missing
Host header in HTTP/1.1 requests.  HttpRequest has been updated to auto-
magically add the host and port to these requests if not explicitly
stated by the client code.

The exception code has been cleaned up to break out of the function
early if such a condition is raised, this avoids unnecessarily executing
code which will ultimately fail.

fixes #11912

Signed-off-by: Gunnar Beutner <gunnar.beutner@netways.de>
doc/6-object-types.md
lib/perfdata/influxdbwriter.cpp
lib/perfdata/influxdbwriter.hpp
lib/perfdata/influxdbwriter.ti
lib/remote/httprequest.cpp

index 3dc32601e069a23c45c74f16aba51eaf55f02f79..08f700e86c0380965510a7eb2fd84b0eb8886b07 100644 (file)
@@ -905,6 +905,7 @@ Configuration Attributes:
   host_template          | **Required.** Host template to define the InfluxDB line protocol.
   service_template       | **Required.** Service template to define the influxDB line protocol.
   enable_send_thresholds | **Optional.** Whether to send warn, crit, min & max tagged data.
+  enable_send_metadata   | **Optional.** Whether to send check metadata e.g. states, execution time, latency etc.
   flush_interval         | **Optional.** How long to buffer data points before transfering to InfluxDB. Defaults to `10s`.
   flush_threshold        | **Optional.** How many data points to buffer before forcing a transfer to InfluxDB.  Defaults to `1024`.
 
index caf9e1dfa0a0e460fa47bbd30131fb8863c5c79e..10290ac4599ff70b42cf3fa7a0c2f3abc3109b09 100644 (file)
@@ -157,10 +157,20 @@ retry:
                }
        }
 
-       SendPerfdata(tmpl, cr, ts);
+       SendPerfdata(tmpl, checkable, cr, ts);
 }
 
-void InfluxdbWriter::SendPerfdata(const Dictionary::Ptr& tmpl, const CheckResult::Ptr& cr, double ts)
+String InfluxdbWriter::FormatInteger(const int val)
+{
+       return Convert::ToString(val) + "i";
+}
+
+String InfluxdbWriter::FormatBoolean(const bool val)
+{
+       return val ? "true" : "false";
+}
+
+void InfluxdbWriter::SendPerfdata(const Dictionary::Ptr& tmpl, const Checkable::Ptr& checkable, const CheckResult::Ptr& cr, double ts)
 {
        Array::Ptr perfdata = cr->GetPerformanceData();
 
@@ -185,6 +195,7 @@ void InfluxdbWriter::SendPerfdata(const Dictionary::Ptr& tmpl, const CheckResult
 
                Dictionary::Ptr fields = new Dictionary();
                fields->Set(String("value"), pdv->GetValue());
+
                if (GetEnableSendThresholds()) {
                        if (pdv->GetCrit())
                                fields->Set(String("crit"), pdv->GetCrit());
@@ -196,6 +207,25 @@ void InfluxdbWriter::SendPerfdata(const Dictionary::Ptr& tmpl, const CheckResult
                                fields->Set(String("max"), pdv->GetMax());
                }
 
+               if (GetEnableSendMetadata()) {
+                       Host::Ptr host;
+                       Service::Ptr service;
+                       boost::tie(host, service) = GetHostService(checkable);
+
+                       if (service)
+                               fields->Set(String("state"), FormatInteger(service->GetState()));
+                       else
+                               fields->Set(String("state"), FormatInteger(host->GetState()));
+
+                       fields->Set(String("current_attempt"), FormatInteger(checkable->GetCheckAttempt()));
+                       fields->Set(String("max_check_attempts"), FormatInteger(checkable->GetMaxCheckAttempts()));
+                       fields->Set(String("state_type"), FormatInteger(checkable->GetStateType()));
+                       fields->Set(String("reachable"), FormatBoolean(checkable->IsReachable()));
+                       fields->Set(String("downtime_depth"), FormatInteger(checkable->GetDowntimeDepth()));
+                       fields->Set(String("latency"), cr->CalculateLatency());
+                       fields->Set(String("execution_time"), cr->CalculateExecutionTime());
+               }
+
                SendMetric(tmpl, pdv->GetLabel(), fields, ts);
        }
 }
@@ -211,8 +241,11 @@ String InfluxdbWriter::EscapeKey(const String& str)
 
 String InfluxdbWriter::EscapeField(const String& str)
 {
-       // Technically everything entering here from PerfdataValue is a
-       // double, but best have the safety net in place.
+       // Handle integers
+       boost::regex integer("-?\\d+i");
+       if (boost::regex_match(str.GetData(), integer)) {
+               return str;
+       }
 
        // Handle numerics
        boost::regex numeric("-?\\d+(\\.\\d+)?((e|E)[+-]?\\d+)?");
@@ -335,6 +368,7 @@ void InfluxdbWriter::Flush(void)
        } catch (const std::exception&) {
                Log(LogWarning, "InfluxdbWriter")
                    << "Cannot write to TCP socket on host '" << GetHost() << "' port '" << GetPort() << "'.";
+               return;
        }
 
        HttpResponse resp(stream, req);
@@ -342,9 +376,10 @@ void InfluxdbWriter::Flush(void)
 
        try {
                resp.Parse(context, true);
-       } catch (const std::exception) {
+       } catch (const std::exception&) {
                Log(LogWarning, "InfluxdbWriter")
                    << "Cannot read from TCP socket from host '" << GetHost() << "' port '" << GetPort() << "'.";
+               return;
        }
 
        if (resp.StatusCode != 204) {
index 22b8060125ae4a4dac9622b0f983859de693cfdc..bdb55b0ebf6e8220c493a9442a2537122859d41c 100644 (file)
@@ -54,11 +54,14 @@ private:
        Array::Ptr m_DataBuffer;
 
        void CheckResultHandler(const Checkable::Ptr& checkable, const CheckResult::Ptr& cr);
-       void SendPerfdata(const Dictionary::Ptr& tmpl, const CheckResult::Ptr& cr, double ts);
+       void SendPerfdata(const Dictionary::Ptr& tmpl, const Checkable::Ptr& checkable, const CheckResult::Ptr& cr, double ts);
        void SendMetric(const Dictionary::Ptr& tmpl, const String& label, const Dictionary::Ptr& fields, double ts);
        void FlushTimeout(void);
        void Flush(void);
 
+       static String FormatInteger(const int val);
+       static String FormatBoolean(const bool val);
+
        static String EscapeKey(const String& str);
        static String EscapeField(const String& str);
 
index 3167e2c331b7702df1652663c2826cb061302684..b77cbc9803d2951b1ba9e925962a8ebebd3ce382 100644 (file)
@@ -81,6 +81,9 @@ class InfluxdbWriter : ConfigObject
        [config] bool enable_send_thresholds {
                default {{{ return false; }}}
        };
+       [config] bool enable_send_metadata {
+               default {{{ return false; }}}
+       };
        [config] int flush_interval {
                default {{{ return 10; }}}
        };
index 6434bff9f9dacd68887bb1e3f4369531b614b7a6..24c40ae11abb09c4b98349d62e0c849b10a7fed7 100644 (file)
@@ -174,8 +174,11 @@ void HttpRequest::FinishHeaders(void)
        if (m_State == HttpRequestHeaders) {
                AddHeader("User-Agent", "Icinga/" + Application::GetAppVersion());
 
-               if (ProtocolVersion == HttpVersion11)
+               if (ProtocolVersion == HttpVersion11) {
                        AddHeader("Transfer-Encoding", "chunked");
+                       if (!Headers->Contains("Host"))
+                               AddHeader("Host", RequestUrl->GetHost() + ":" + RequestUrl->GetPort());
+               }
 
                ObjectLock olock(Headers);
                BOOST_FOREACH(const Dictionary::Pair& kv, Headers)