From f8e102c15ab6a93a88ec7f91b2f6148c2efe56a6 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 --- 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 f113aef13..8b6441c87 100644 --- a/lib/perfdata/elasticsearchwriter.cpp +++ b/lib/perfdata/elasticsearchwriter.cpp @@ -396,6 +396,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); } @@ -455,12 +460,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. */ @@ -479,10 +492,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") { @@ -509,6 +518,8 @@ void ElasticsearchWriter::SendRequest(const String& body) Log(LogCritical, "ElasticsearchWriter") << "Elasticsearch error message:\n" << error; + + return; } }