[icinga-checkins] icinga.org: icinga2/master: Add service metadata to InfluxDB Writer

git at icinga.org git at icinga.org
Wed Jun 8 13:24:13 CEST 2016


Module: icinga2
Branch: master
Commit: 2e8c8809eac35a4b401c20b9cfbe5374efbc4827
URL:    https://git.icinga.org/?p=icinga2.git;a=commit;h=2e8c8809eac35a4b401c20b9cfbe5374efbc4827

Author: Simon Murray <spjmurray at yahoo.co.uk>
Date:   Wed Jun  8 11:09:21 2016 +0100

Add service metadata to InfluxDB Writer

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 at netways.de>

---

 doc/6-object-types.md           |    1 +
 lib/perfdata/influxdbwriter.cpp |   45 ++++++++++++++++++++++++++++++++++-----
 lib/perfdata/influxdbwriter.hpp |    5 ++++-
 lib/perfdata/influxdbwriter.ti  |    3 +++
 lib/remote/httprequest.cpp      |    5 ++++-
 5 files changed, 52 insertions(+), 7 deletions(-)

diff --git a/doc/6-object-types.md b/doc/6-object-types.md
index 3dc3260..08f700e 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 caf9e1d..10290ac 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 22b8060..bdb55b0 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 3167e2c..b77cbc9 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 6434bff..24c40ae 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)



More information about the icinga-checkins mailing list