From: Simon Murray <spjmurray@yahoo.co.uk>
Date: Thu, 28 Jul 2016 09:28:53 +0000 (+0100)
Subject: Fix InfluxdbWriter Trailing Backslash
X-Git-Tag: v2.5.0~164
X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=84ea0065b2e8f8ffd870ea6915fa6dea31101361;p=icinga2

Fix InfluxdbWriter Trailing Backslash

Backslashes escape spaces or commas (and evidently equals), given tags are
separated by commas, tag keys and values are separated by equals and tags
are separated from fields by a space we need to take action when these end
in a backslash e.g. 'C:\'.  Also discovered a bug whereby the metric tag was
missing out on escaping.

fixes #12227

Signed-off-by: Gunnar Beutner <gunnar.beutner@netways.de>
---

diff --git a/doc/6-object-types.md b/doc/6-object-types.md
index 9e3e7e9af..3b87ff8a1 100644
--- a/doc/6-object-types.md
+++ b/doc/6-object-types.md
@@ -900,6 +900,11 @@ perfdata label. Fields (value, warn, crit, min, max) are created from data if av
 and the configuration allows it.  If a value associated with a tag is not able to be
 resolved, it will be dropped and not sent to the target host.
 
+Backslashes are allowed in tag keys, tag values and field keys, however they are also
+escape characters when followed by a space or comma, but cannot be escaped themselves.
+As a result all trailling slashes in these fields are replaced with an underscore.  This
+predominantly affects Windows paths e.g. `C:\` becomes `C:_`.
+
 The database is assumed to exist so this object will make no attempt to create it currently.
 
 Configuration Attributes:
diff --git a/lib/perfdata/influxdbwriter.cpp b/lib/perfdata/influxdbwriter.cpp
index 92091aafb..6eb8d0091 100644
--- a/lib/perfdata/influxdbwriter.cpp
+++ b/lib/perfdata/influxdbwriter.cpp
@@ -237,6 +237,16 @@ String InfluxdbWriter::EscapeKey(const String& str)
 	String result = str;
 	boost::algorithm::replace_all(result, ",", "\\,");
 	boost::algorithm::replace_all(result, " ", "\\ ");
+
+	// InfluxDB 'feature': although backslashes are allowed in keys they also act
+	// as escape sequences when followed by ',' or ' '.  When your tag is like
+	// 'metric=C:\' bad things happen.  Backslashes themselves cannot be escaped
+	// and through experimentation they also escape '='.  To be safe we replace
+	// trailing backslashes with and underscore.
+	size_t length = result.GetLength();
+	if (result[length - 1] == '\\')
+		result[length - 1] = '_';
+
 	return result;
 }
 
@@ -284,7 +294,7 @@ void InfluxdbWriter::SendMetric(const Dictionary::Ptr& tmpl, const String& label
 		}
 	}
 
-	msgbuf << ",metric=" << label << " ";
+	msgbuf << ",metric=" << EscapeKey(label) << " ";
 
 	bool first = true;
 	ObjectLock fieldLock(fields);