From 04e7dc127017634045793665d0741cbb370b3506 Mon Sep 17 00:00:00 2001 From: Aleric Inglewood Date: Sat, 10 Nov 2012 02:19:20 +0100 Subject: [PATCH] Collect and print stats about HTTP status code --- indra/llmessage/aicurl.cpp | 34 +++++++++++++ indra/llmessage/aicurl.h | 6 +++ indra/llmessage/aicurlthread.cpp | 1 + indra/llmessage/llhttpclient.cpp | 85 +++++++++++++++++--------------- 4 files changed, 85 insertions(+), 41 deletions(-) diff --git a/indra/llmessage/aicurl.cpp b/indra/llmessage/aicurl.cpp index 36ed41b1d..3aacd0ecd 100644 --- a/indra/llmessage/aicurl.cpp +++ b/indra/llmessage/aicurl.cpp @@ -303,6 +303,21 @@ LLAtomicU32 Stats::AICurlEasyRequestStateMachine_count; LLAtomicU32 Stats::BufferedCurlEasyRequest_count; LLAtomicU32 Stats::ResponderBase_count; LLAtomicU32 Stats::ThreadSafeBufferedCurlEasyRequest_count; +LLAtomicU32 Stats::status_count[100]; +LLAtomicU32 Stats::llsd_body_count; +LLAtomicU32 Stats::llsd_body_parse_error; +LLAtomicU32 Stats::raw_body_count; + +U32 Stats::status2index(U32 status) +{ + llassert_always(status >= 100 && status < 600 && (status % 100) < 20); // Max value 519. + return (status - 100) / 100 * 20 + status % 100; // Returns 0..99 (for status 100..519). +} + +U32 Stats::index2status(U32 index) +{ + return 100 + (index / 20) * 100 + index % 20; +} // MAIN-THREAD void initCurl(void) @@ -448,6 +463,25 @@ void Stats::print(void) llinfos_nf << " Current number of AICurlEasyRequestStateMachine objects: " << AICurlEasyRequestStateMachine_count << llendl; #endif llinfos_nf << " Current number of Responders: " << ResponderBase_count << llendl; + llinfos_nf << " Received HTTP bodies LLSD / LLSD parse errors / non-LLSD: " << llsd_body_count << "/" << llsd_body_parse_error << "/" << raw_body_count << llendl; + llinfos_nf << " Received HTTP status codes: status (count) [...]: "; + bool first = true; + for (U32 index = 0; index < 100; ++index) + { + if (status_count[index] > 0) + { + if (!first) + { + llcont << ", "; + } + else + { + first = false; + } + llcont << index2status(index) << " (" << status_count[index] << ')'; + } + } + llcont << llendl; llinfos_nf << "========= END OF CURL STATS =========" << llendl; // Leak tests. // There is one easy handle per CurlEasyHandle, and BufferedCurlEasyRequest is derived from that. diff --git a/indra/llmessage/aicurl.h b/indra/llmessage/aicurl.h index e6e506d93..b7599c817 100644 --- a/indra/llmessage/aicurl.h +++ b/indra/llmessage/aicurl.h @@ -140,8 +140,14 @@ struct Stats { static LLAtomicU32 BufferedCurlEasyRequest_count; static LLAtomicU32 ResponderBase_count; static LLAtomicU32 ThreadSafeBufferedCurlEasyRequest_count; + static LLAtomicU32 status_count[100]; + static LLAtomicU32 llsd_body_count; + static LLAtomicU32 llsd_body_parse_error; + static LLAtomicU32 raw_body_count; static void print(void); + static U32 status2index(U32 status); + static U32 index2status(U32 index); }; //----------------------------------------------------------------------------- diff --git a/indra/llmessage/aicurlthread.cpp b/indra/llmessage/aicurlthread.cpp index ab6bc4aea..8a4c8482d 100644 --- a/indra/llmessage/aicurlthread.cpp +++ b/indra/llmessage/aicurlthread.cpp @@ -2043,6 +2043,7 @@ void BufferedCurlEasyRequest::setStatusAndReason(U32 status, std::string const& { mStatus = status; mReason = reason; + AICurlInterface::Stats::status_count[AICurlInterface::Stats::status2index(mStatus)]++; } void BufferedCurlEasyRequest::processOutput(void) diff --git a/indra/llmessage/llhttpclient.cpp b/indra/llmessage/llhttpclient.cpp index a24138fe1..b2bf549ab 100644 --- a/indra/llmessage/llhttpclient.cpp +++ b/indra/llmessage/llhttpclient.cpp @@ -264,73 +264,76 @@ void LLHTTPClient::get(std::string const& url, LLSD const& query, ResponderPtr r LLHTTPClient::ResponderBase::ResponderBase(void) : mReferenceCount(0), mCode(CURLE_FAILED_INIT), mFinished(false) { - DoutEntering(dc::curl, "AICurlInterface::Responder() with this = " << (void*)this); - AICurlInterface::Stats::ResponderBase_count++; + DoutEntering(dc::curl, "AICurlInterface::Responder() with this = " << (void*)this); + AICurlInterface::Stats::ResponderBase_count++; } LLHTTPClient::ResponderBase::~ResponderBase() { - DoutEntering(dc::curl, "AICurlInterface::ResponderBase::~ResponderBase() with this = " << (void*)this << "; mReferenceCount = " << mReferenceCount); - llassert(mReferenceCount == 0); - --AICurlInterface::Stats::ResponderBase_count; + DoutEntering(dc::curl, "AICurlInterface::ResponderBase::~ResponderBase() with this = " << (void*)this << "; mReferenceCount = " << mReferenceCount); + llassert(mReferenceCount == 0); + --AICurlInterface::Stats::ResponderBase_count; } void LLHTTPClient::ResponderBase::setURL(std::string const& url) { - // setURL is called from llhttpclient.cpp (request()), before calling any of the below (of course). - // We don't need locking here therefore; it's a case of initializing before use. - mURL = url; + // setURL is called from llhttpclient.cpp (request()), before calling any of the below (of course). + // We don't need locking here therefore; it's a case of initializing before use. + mURL = url; } AIHTTPTimeoutPolicy const& LLHTTPClient::ResponderBase::getHTTPTimeoutPolicy(void) const { - return AIHTTPTimeoutPolicy::getDebugSettingsCurlTimeout(); + return AIHTTPTimeoutPolicy::getDebugSettingsCurlTimeout(); } void LLHTTPClient::ResponderBase::decode_llsd_body(U32 status, std::string const& reason, LLChannelDescriptors const& channels, buffer_ptr_t const& buffer, LLSD& content) { - // If the status indicates success (and we get here) then we expect the body to be LLSD. - bool const should_be_llsd = (200 <= status && status < 300); - if (should_be_llsd) - { - LLBufferStream istr(channels, buffer.get()); - if (LLSDSerialize::fromXML(content, istr) == LLSDParser::PARSE_FAILURE) + AICurlInterface::Stats::llsd_body_count++; + // If the status indicates success (and we get here) then we expect the body to be LLSD. + bool const should_be_llsd = (200 <= status && status < 300); + if (should_be_llsd) { - // Unfortunately we can't show the body of the message... I think this is a pretty serious error - // though, so if this ever happens it has to be investigated by making a copy of the buffer - // before serializing it, as is done below. - llwarns << "Failed to deserialize LLSD. " << mURL << " [" << status << "]: " << reason << llendl; + LLBufferStream istr(channels, buffer.get()); + if (LLSDSerialize::fromXML(content, istr) == LLSDParser::PARSE_FAILURE) + { + // Unfortunately we can't show the body of the message... I think this is a pretty serious error + // though, so if this ever happens it has to be investigated by making a copy of the buffer + // before serializing it, as is done below. + llwarns << "Failed to deserialize LLSD. " << mURL << " [" << status << "]: " << reason << llendl; + AICurlInterface::Stats::llsd_body_parse_error++; + } + // LLSDSerialize::fromXML destructed buffer, we can't initialize content now. + return; } - // LLSDSerialize::fromXML destructed buffer, we can't initialize content now. - return; - } - // Put the body in content as-is. - std::stringstream ss; - buffer->writeChannelTo(ss, channels.in()); - content = ss.str(); + // Put the body in content as-is. + std::stringstream ss; + buffer->writeChannelTo(ss, channels.in()); + content = ss.str(); #ifdef SHOW_ASSERT - if (!should_be_llsd) - { - char const* str = ss.str().c_str(); - // Make sure that the server indeed never returns LLSD as body when the http status is an error. - LLSD dummy; - bool server_sent_llsd_with_http_error = - strncmp(str, " 0; - if (server_sent_llsd_with_http_error) + if (!should_be_llsd) { - llwarns << "The server sent us a response with http status " << status << " and LLSD(!) body: \"" << ss.str() << "\"!" << llendl; + char const* str = ss.str().c_str(); + // Make sure that the server indeed never returns LLSD as body when the http status is an error. + LLSD dummy; + bool server_sent_llsd_with_http_error = + strncmp(str, " 0; + if (server_sent_llsd_with_http_error) + { + llwarns << "The server sent us a response with http status " << status << " and LLSD(!) body: \"" << ss.str() << "\"!" << llendl; + } + llassert(!server_sent_llsd_with_http_error); } - llassert(!server_sent_llsd_with_http_error); - } #endif } void LLHTTPClient::ResponderBase::decode_raw_body(U32 status, std::string const& reason, LLChannelDescriptors const& channels, buffer_ptr_t const& buffer, std::string& content) { + AICurlInterface::Stats::raw_body_count++; LLMutexLock lock(buffer->getMutex()); LLBufferArray::const_segment_iterator_t const end = buffer->endSegment(); for (LLBufferArray::const_segment_iterator_t iter = buffer->beginSegment(); iter != end; ++iter)