diff --git a/doc/6-object-types.md b/doc/6-object-types.md index 3dc32601e..08f700e86 100644 --- a/doc/6-object-types.md +++ b/doc/6-object-types.md @@ -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`. diff --git a/lib/perfdata/influxdbwriter.cpp b/lib/perfdata/influxdbwriter.cpp index caf9e1dfa..10290ac45 100644 --- a/lib/perfdata/influxdbwriter.cpp +++ b/lib/perfdata/influxdbwriter.cpp @@ -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) { diff --git a/lib/perfdata/influxdbwriter.hpp b/lib/perfdata/influxdbwriter.hpp index 22b806012..bdb55b0eb 100644 --- a/lib/perfdata/influxdbwriter.hpp +++ b/lib/perfdata/influxdbwriter.hpp @@ -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); diff --git a/lib/perfdata/influxdbwriter.ti b/lib/perfdata/influxdbwriter.ti index 3167e2c33..b77cbc980 100644 --- a/lib/perfdata/influxdbwriter.ti +++ b/lib/perfdata/influxdbwriter.ti @@ -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; }}} }; diff --git a/lib/remote/httprequest.cpp b/lib/remote/httprequest.cpp index 6434bff9f..24c40ae11 100644 --- a/lib/remote/httprequest.cpp +++ b/lib/remote/httprequest.cpp @@ -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)