From 806eb0d2d2b077a9a4bac073bfbb27c2af369008 Mon Sep 17 00:00:00 2001 From: Michael Friedrich Date: Thu, 7 Dec 2017 11:11:03 +0100 Subject: [PATCH] Fix newline terminator for bulk requests in ElasticsearchWriter This enables compatibility with 6.x. This commit also fixes an incorrect HTTP response parsing which could lead into false positives. Analysis and fix in https://github.com/Icinga/icinga2/issues/5795#issuecomment-349920587 fixes #5795 refs #5840 --- lib/perfdata/elasticsearchwriter.cpp | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/lib/perfdata/elasticsearchwriter.cpp b/lib/perfdata/elasticsearchwriter.cpp index 69221fd88..2171752ca 100644 --- a/lib/perfdata/elasticsearchwriter.cpp +++ b/lib/perfdata/elasticsearchwriter.cpp @@ -395,6 +395,11 @@ void ElasticsearchWriter::Flush(void) String body = boost::algorithm::join(m_DataBuffer, "\n"); m_DataBuffer.clear(); + /* Elasticsearch 6.x requires a new line. This is compatible to 5.x. + * Tested with 6.0.0 and 5.6.4. + */ + body += "\n"; + SendRequest(body); } @@ -454,12 +459,20 @@ void ElasticsearchWriter::SendRequest(const String& body) try { resp.Parse(context, true); + while (resp.Parse(context, true) && !resp.Complete) + ; /* Do nothing */ } catch (const std::exception& ex) { Log(LogWarning, "ElasticsearchWriter") - << "Cannot read from HTTP API on host '" << GetHost() << "' port '" << GetPort() << "'."; + << "Failed to parse HTTP response from host '" << GetHost() << "' port '" << GetPort() << "': " << DiagnosticInformation(ex, false); throw ex; } + if (!resp.Complete) { + Log(LogWarning, "ElasticsearchWriter") + << "Failed to read a complete HTTP response from the Elasticsearch server."; + return; + } + if (resp.StatusCode > 299) { if (resp.StatusCode == 401) { /* More verbose error logging with Elasticsearch is hidden behind a proxy. */ @@ -478,10 +491,6 @@ void ElasticsearchWriter::SendRequest(const String& body) Log(LogWarning, "ElasticsearchWriter") << "Unexpected response code " << resp.StatusCode; - /* Finish parsing the headers and body. */ - while (!resp.Complete) - resp.Parse(context, true); - String contentType = resp.Headers->Get("content-type"); if (contentType != "application/json") { @@ -508,6 +517,8 @@ void ElasticsearchWriter::SendRequest(const String& body) Log(LogCritical, "ElasticsearchWriter") << "Elasticsearch error message:\n" << error; + + return; } } -- 2.40.0