Verbose InfluxDB Error Logging

On a non 204 response we parse the HTTP response until complete e.g. do the headers
and body, not just the header.  A new interface is added to the response to allow us
to determine the body size so that it may be read out and buffered.  The body is
parsed and any error message printed out.  In the event that the parsing fails the
raw body is dumped out; better than nothing!

fixes #4411

Signed-off-by: Michael Friedrich <michael.friedrich@icinga.com>
This commit is contained in:
Simon Murray 2016-07-28 13:29:37 +01:00 committed by Michael Friedrich
parent 2196c6ea02
commit fc2c2d9a29
3 changed files with 41 additions and 0 deletions

View File

@ -34,6 +34,7 @@
#include "base/convert.hpp" #include "base/convert.hpp"
#include "base/utility.hpp" #include "base/utility.hpp"
#include "base/stream.hpp" #include "base/stream.hpp"
#include "base/json.hpp"
#include "base/networkstream.hpp" #include "base/networkstream.hpp"
#include "base/exception.hpp" #include "base/exception.hpp"
#include "base/statsfunction.hpp" #include "base/statsfunction.hpp"
@ -43,6 +44,7 @@
#include <boost/algorithm/string/split.hpp> #include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/replace.hpp> #include <boost/algorithm/string/replace.hpp>
#include <boost/regex.hpp> #include <boost/regex.hpp>
#include <boost/scoped_array.hpp>
using namespace icinga; using namespace icinga;
@ -507,6 +509,36 @@ void InfluxdbWriter::FlushHandler(const String& body)
if (resp.StatusCode != 204) { if (resp.StatusCode != 204) {
Log(LogWarning, "InfluxdbWriter") Log(LogWarning, "InfluxdbWriter")
<< "Unexpected response code " << resp.StatusCode; << "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") {
Log(LogWarning, "InfluxdbWriter")
<< "Unexpected Content-Type: " << contentType;
return;
}
size_t responseSize = resp.GetBodySize();
boost::scoped_array<char> buffer(new char[responseSize + 1]);
resp.ReadBody(buffer.get(), responseSize);
buffer.get()[responseSize] = '\0';
Dictionary::Ptr jsonResponse;
try {
jsonResponse = JsonDecode(buffer.get());
} catch (...) {
Log(LogWarning, "InfluxdbWriter")
<< "Unable to parse JSON response:\n" << buffer.get();
return;
}
String error = jsonResponse->Get("error");
Log(LogCritical, "InfluxdbWriter")
<< "InfluxDB error message:\n" << error;
} }
} }

View File

@ -241,6 +241,14 @@ size_t HttpResponse::ReadBody(char *data, size_t count)
return m_Body->Read(data, count, true); return m_Body->Read(data, count, true);
} }
size_t HttpResponse::GetBodySize(void) const
{
if (!m_Body)
return 0;
else
return m_Body->GetAvailableBytes();
}
bool HttpResponse::IsPeerConnected(void) const bool HttpResponse::IsPeerConnected(void) const
{ {
return !m_Stream->IsEof(); return !m_Stream->IsEof();

View File

@ -55,6 +55,7 @@ public:
bool Parse(StreamReadContext& src, bool may_wait); bool Parse(StreamReadContext& src, bool may_wait);
size_t ReadBody(char *data, size_t count); size_t ReadBody(char *data, size_t count);
size_t GetBodySize(void) const;
void SetStatus(int code, const String& message); void SetStatus(int code, const String& message);
void AddHeader(const String& key, const String& value); void AddHeader(const String& key, const String& value);