1
0
Fork 0

added statistics

This commit is contained in:
Frank Celler 2012-07-04 18:33:13 +02:00
parent 935926bd8b
commit 795b2a9178
15 changed files with 1103 additions and 291 deletions

View File

@ -386,7 +386,7 @@ am__lib_libarango_a_SOURCES_DIST = lib/Basics/ConditionLocker.cpp \
lib/Rest/JsonContainer.cpp lib/Rest/SslInterface.cpp \
lib/Rest/Url.cpp lib/ShapedJson/json-shaper.c \
lib/ShapedJson/shape-accessor.c lib/ShapedJson/shaped-json.c \
lib/Statistics/request-statistics.c \
lib/Statistics/request-statistics.cpp \
lib/Statistics/statistics.c lib/Utilities/LineEditor.cpp \
lib/Utilities/ScriptLoader.cpp lib/Variant/VariantArray.cpp \
lib/Variant/VariantBlob.cpp lib/Variant/VariantBoolean.cpp \
@ -642,6 +642,7 @@ am__bin_arangod_SOURCES_DIST = arangod/Actions/actions.cpp \
arangod/IndexOperators/index-operator.c \
arangod/PriorityQueue/pqueueindex.c \
arangod/PriorityQueue/priorityqueue.c \
arangod/RestHandler/RequestStatisticsHandler.cpp \
arangod/RestHandler/RestBatchHandler.cpp \
arangod/RestHandler/RestDocumentHandler.cpp \
arangod/RestHandler/RestEdgeHandler.cpp \
@ -702,6 +703,7 @@ am_bin_arangod_OBJECTS = \
arangod/IndexOperators/bin_arangod-index-operator.$(OBJEXT) \
arangod/PriorityQueue/bin_arangod-pqueueindex.$(OBJEXT) \
arangod/PriorityQueue/bin_arangod-priorityqueue.$(OBJEXT) \
arangod/RestHandler/bin_arangod-RequestStatisticsHandler.$(OBJEXT) \
arangod/RestHandler/bin_arangod-RestBatchHandler.$(OBJEXT) \
arangod/RestHandler/bin_arangod-RestDocumentHandler.$(OBJEXT) \
arangod/RestHandler/bin_arangod-RestEdgeHandler.$(OBJEXT) \
@ -1299,7 +1301,7 @@ lib_libarango_a_SOURCES = lib/Basics/ConditionLocker.cpp \
lib/Rest/JsonContainer.cpp lib/Rest/SslInterface.cpp \
lib/Rest/Url.cpp lib/ShapedJson/json-shaper.c \
lib/ShapedJson/shape-accessor.c lib/ShapedJson/shaped-json.c \
lib/Statistics/request-statistics.c \
lib/Statistics/request-statistics.cpp \
lib/Statistics/statistics.c lib/Utilities/LineEditor.cpp \
lib/Utilities/ScriptLoader.cpp lib/Variant/VariantArray.cpp \
lib/Variant/VariantBlob.cpp lib/Variant/VariantBoolean.cpp \
@ -1441,6 +1443,7 @@ bin_arangod_SOURCES = arangod/Actions/actions.cpp \
arangod/IndexOperators/index-operator.c \
arangod/PriorityQueue/pqueueindex.c \
arangod/PriorityQueue/priorityqueue.c \
arangod/RestHandler/RequestStatisticsHandler.cpp \
arangod/RestHandler/RestBatchHandler.cpp \
arangod/RestHandler/RestDocumentHandler.cpp \
arangod/RestHandler/RestEdgeHandler.cpp \
@ -2577,6 +2580,9 @@ arangod/RestHandler/$(am__dirstamp):
arangod/RestHandler/$(DEPDIR)/$(am__dirstamp):
@$(MKDIR_P) arangod/RestHandler/$(DEPDIR)
@: > arangod/RestHandler/$(DEPDIR)/$(am__dirstamp)
arangod/RestHandler/bin_arangod-RequestStatisticsHandler.$(OBJEXT): \
arangod/RestHandler/$(am__dirstamp) \
arangod/RestHandler/$(DEPDIR)/$(am__dirstamp)
arangod/RestHandler/bin_arangod-RestBatchHandler.$(OBJEXT): \
arangod/RestHandler/$(am__dirstamp) \
arangod/RestHandler/$(DEPDIR)/$(am__dirstamp)
@ -2827,6 +2833,7 @@ mostlyclean-compile:
-rm -f arangod/MRServer/bin_arangod-mr-actions.$(OBJEXT)
-rm -f arangod/PriorityQueue/bin_arangod-pqueueindex.$(OBJEXT)
-rm -f arangod/PriorityQueue/bin_arangod-priorityqueue.$(OBJEXT)
-rm -f arangod/RestHandler/bin_arangod-RequestStatisticsHandler.$(OBJEXT)
-rm -f arangod/RestHandler/bin_arangod-RestBatchHandler.$(OBJEXT)
-rm -f arangod/RestHandler/bin_arangod-RestDocumentHandler.$(OBJEXT)
-rm -f arangod/RestHandler/bin_arangod-RestEdgeHandler.$(OBJEXT)
@ -3088,6 +3095,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@arangod/MRServer/$(DEPDIR)/bin_arangod-mr-actions.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@arangod/PriorityQueue/$(DEPDIR)/bin_arangod-pqueueindex.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@arangod/PriorityQueue/$(DEPDIR)/bin_arangod-priorityqueue.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@arangod/RestHandler/$(DEPDIR)/bin_arangod-RequestStatisticsHandler.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@arangod/RestHandler/$(DEPDIR)/bin_arangod-RestBatchHandler.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@arangod/RestHandler/$(DEPDIR)/bin_arangod-RestDocumentHandler.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@arangod/RestHandler/$(DEPDIR)/bin_arangod-RestEdgeHandler.Po@am__quote@
@ -4192,6 +4200,22 @@ arangod/Actions/bin_arangod-RestActionHandler.obj: arangod/Actions/RestActionHan
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bin_arangod_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o arangod/Actions/bin_arangod-RestActionHandler.obj `if test -f 'arangod/Actions/RestActionHandler.cpp'; then $(CYGPATH_W) 'arangod/Actions/RestActionHandler.cpp'; else $(CYGPATH_W) '$(srcdir)/arangod/Actions/RestActionHandler.cpp'; fi`
arangod/RestHandler/bin_arangod-RequestStatisticsHandler.o: arangod/RestHandler/RequestStatisticsHandler.cpp
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bin_arangod_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT arangod/RestHandler/bin_arangod-RequestStatisticsHandler.o -MD -MP -MF arangod/RestHandler/$(DEPDIR)/bin_arangod-RequestStatisticsHandler.Tpo -c -o arangod/RestHandler/bin_arangod-RequestStatisticsHandler.o `test -f 'arangod/RestHandler/RequestStatisticsHandler.cpp' || echo '$(srcdir)/'`arangod/RestHandler/RequestStatisticsHandler.cpp
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) arangod/RestHandler/$(DEPDIR)/bin_arangod-RequestStatisticsHandler.Tpo arangod/RestHandler/$(DEPDIR)/bin_arangod-RequestStatisticsHandler.Po
@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='arangod/RestHandler/RequestStatisticsHandler.cpp' object='arangod/RestHandler/bin_arangod-RequestStatisticsHandler.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bin_arangod_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o arangod/RestHandler/bin_arangod-RequestStatisticsHandler.o `test -f 'arangod/RestHandler/RequestStatisticsHandler.cpp' || echo '$(srcdir)/'`arangod/RestHandler/RequestStatisticsHandler.cpp
arangod/RestHandler/bin_arangod-RequestStatisticsHandler.obj: arangod/RestHandler/RequestStatisticsHandler.cpp
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bin_arangod_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT arangod/RestHandler/bin_arangod-RequestStatisticsHandler.obj -MD -MP -MF arangod/RestHandler/$(DEPDIR)/bin_arangod-RequestStatisticsHandler.Tpo -c -o arangod/RestHandler/bin_arangod-RequestStatisticsHandler.obj `if test -f 'arangod/RestHandler/RequestStatisticsHandler.cpp'; then $(CYGPATH_W) 'arangod/RestHandler/RequestStatisticsHandler.cpp'; else $(CYGPATH_W) '$(srcdir)/arangod/RestHandler/RequestStatisticsHandler.cpp'; fi`
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) arangod/RestHandler/$(DEPDIR)/bin_arangod-RequestStatisticsHandler.Tpo arangod/RestHandler/$(DEPDIR)/bin_arangod-RequestStatisticsHandler.Po
@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='arangod/RestHandler/RequestStatisticsHandler.cpp' object='arangod/RestHandler/bin_arangod-RequestStatisticsHandler.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bin_arangod_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o arangod/RestHandler/bin_arangod-RequestStatisticsHandler.obj `if test -f 'arangod/RestHandler/RequestStatisticsHandler.cpp'; then $(CYGPATH_W) 'arangod/RestHandler/RequestStatisticsHandler.cpp'; else $(CYGPATH_W) '$(srcdir)/arangod/RestHandler/RequestStatisticsHandler.cpp'; fi`
arangod/RestHandler/bin_arangod-RestBatchHandler.o: arangod/RestHandler/RestBatchHandler.cpp
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bin_arangod_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT arangod/RestHandler/bin_arangod-RestBatchHandler.o -MD -MP -MF arangod/RestHandler/$(DEPDIR)/bin_arangod-RestBatchHandler.Tpo -c -o arangod/RestHandler/bin_arangod-RestBatchHandler.o `test -f 'arangod/RestHandler/RestBatchHandler.cpp' || echo '$(srcdir)/'`arangod/RestHandler/RestBatchHandler.cpp
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) arangod/RestHandler/$(DEPDIR)/bin_arangod-RestBatchHandler.Tpo arangod/RestHandler/$(DEPDIR)/bin_arangod-RestBatchHandler.Po

View File

@ -55,6 +55,7 @@ bin_arangod_SOURCES = \
arangod/IndexOperators/index-operator.c \
arangod/PriorityQueue/pqueueindex.c \
arangod/PriorityQueue/priorityqueue.c \
arangod/RestHandler/RequestStatisticsHandler.cpp \
arangod/RestHandler/RestBatchHandler.cpp \
arangod/RestHandler/RestDocumentHandler.cpp \
arangod/RestHandler/RestEdgeHandler.cpp \

View File

@ -0,0 +1,209 @@
////////////////////////////////////////////////////////////////////////////////
/// @brief statistics handler
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2004-2012 triagens GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is triAGENS GmbH, Cologne, Germany
///
/// @author Dr. Frank Celler
/// @author Copyright 2010-2012, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////
#include "RequestStatisticsHandler.h"
#include "Basics/StringUtils.h"
#include "Rest/HttpRequest.h"
#include "Variant/VariantArray.h"
using namespace triagens::arango;
using namespace triagens::basics;
using namespace triagens::rest;
// -----------------------------------------------------------------------------
// --SECTION-- constructors and destructors
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup ArangoDB
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief constructs a new handler
////////////////////////////////////////////////////////////////////////////////
RequestStatisticsHandler::RequestStatisticsHandler (HttpRequest* request)
: RestBaseHandler(request) {
}
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- Handler methods
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup ArangoDB
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// {@inheritDoc}
////////////////////////////////////////////////////////////////////////////////
bool RequestStatisticsHandler::isDirect () {
return true;
}
////////////////////////////////////////////////////////////////////////////////
/// {@inheritDoc}
////////////////////////////////////////////////////////////////////////////////
Handler::status_e RequestStatisticsHandler::execute () {
bool showTotalTime = false;
bool showQueueTime = false;
bool showRequestTime = false;
bool showBytesSent = false;
bool showBytesReceived = false;
TRI_request_statistics_granularity_e granularity = TRI_REQUEST_STATISTICS_MINUTES;
int length = -1;
// .............................................................................
// extract the figures to show
// .............................................................................
bool found;
string figures = StringUtils::tolower(_request->value("figures", found));
if (found) {
if (figures == "*" || figures == "all") {
showTotalTime = true;
showQueueTime = true;
showRequestTime = true;
showBytesSent = true;
showBytesReceived = true;
}
else {
vector<string> f = StringUtils::split(figures);
for (vector<string>::iterator i = f.begin(); i != f.end(); ++i) {
string const& fn = *i;
if (fn == "totaltime") {
showTotalTime = true;
}
else if (fn == "queuetime") {
showQueueTime = true;
}
else if (fn == "requesttime") {
showRequestTime = true;
}
else if (fn == "bytessent") {
showBytesSent = true;
}
else if (fn == "bytesreceived") {
showBytesReceived = true;
}
else {
generateError(HttpResponse::BAD, TRI_ERROR_HTTP_BAD_PARAMETER, "unknown figure '" + fn + "'");
return HANDLER_DONE;
}
}
}
}
else {
showTotalTime = true;
showBytesSent = true;
showBytesReceived = true;
}
// .............................................................................
// extract the granularity to show
// .............................................................................
string gran = StringUtils::tolower(_request->value("granularity", found));
if (found) {
if (gran == "minute" || gran == "minutes") {
granularity = TRI_REQUEST_STATISTICS_MINUTES;
}
else if (gran == "hour" || gran == "hours") {
granularity = TRI_REQUEST_STATISTICS_HOURS;
}
else if (gran == "day" || gran == "days") {
granularity = TRI_REQUEST_STATISTICS_DAYS;
}
}
else {
granularity = TRI_REQUEST_STATISTICS_MINUTES;
}
// .............................................................................
// extract the length
// .............................................................................
string l = StringUtils::tolower(_request->value("length", found));
if (found) {
if (l == "current") {
length = 0;
}
else {
length = StringUtils::uint32(l);
}
}
else {
length = -1;
}
// .............................................................................
// extract the statistics blocks
// .............................................................................
VariantArray* result = TRI_RequestStatistics(granularity,
length,
showTotalTime,
showQueueTime,
showRequestTime,
showBytesSent,
showBytesReceived);
generateResult(result);
return HANDLER_DONE;
}
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- END-OF-FILE
// -----------------------------------------------------------------------------
// Local Variables:
// mode: outline-minor
// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|/// @page\\|// --SECTION--\\|/// @\\}\\)"
// End:

View File

@ -0,0 +1,117 @@
////////////////////////////////////////////////////////////////////////////////
/// @brief statistics handler
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2004-2012 triagens GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is triAGENS GmbH, Cologne, Germany
///
/// @author Dr. Frank Celler
/// @author Copyright 2010-2012, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////
#ifndef TRIAGENS_REST_HANDLER_REQUEST_STATISTICS_HANDLER_H
#define TRIAGENS_REST_HANDLER_REQUEST_STATISTICS_HANDLER_H 1
#include "Admin/RestBaseHandler.h"
// -----------------------------------------------------------------------------
// --SECTION-- class RestDocumentHandler
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup ArangoDB
/// @{
////////////////////////////////////////////////////////////////////////////////
namespace triagens {
namespace arango {
////////////////////////////////////////////////////////////////////////////////
/// @brief statistics handler
////////////////////////////////////////////////////////////////////////////////
class RequestStatisticsHandler : public admin::RestBaseHandler {
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- constructors and destructors
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup ArangoDB
/// @{
////////////////////////////////////////////////////////////////////////////////
public:
////////////////////////////////////////////////////////////////////////////////
/// @brief constructs a new handler
////////////////////////////////////////////////////////////////////////////////
RequestStatisticsHandler (rest::HttpRequest*);
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- Handler methods
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup ArangoDB
/// @{
////////////////////////////////////////////////////////////////////////////////
public:
////////////////////////////////////////////////////////////////////////////////
/// {@inheritDoc}
////////////////////////////////////////////////////////////////////////////////
bool isDirect ();
////////////////////////////////////////////////////////////////////////////////
/// {@inheritDoc}
////////////////////////////////////////////////////////////////////////////////
status_e execute ();
};
}
}
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
#endif
// -----------------------------------------------------------------------------
// --SECTION-- END-OF-FILE
// -----------------------------------------------------------------------------
// Local Variables:
// mode: outline-minor
// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|/// @page\\|// --SECTION--\\|/// @\\}\\)"
// End:

View File

@ -31,7 +31,7 @@
#include "RestHandler/RestVocbaseBaseHandler.h"
// -----------------------------------------------------------------------------
// --SECTION-- RestDocumentHandler
// --SECTION-- class RestDocumentHandler
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
@ -43,7 +43,7 @@ namespace triagens {
namespace arango {
////////////////////////////////////////////////////////////////////////////////
/// @brief collection request handler
/// @brief document request handler
////////////////////////////////////////////////////////////////////////////////
class RestDocumentHandler : public RestVocbaseBaseHandler {

View File

@ -47,7 +47,7 @@ struct TRI_vocbase_s;
struct TRI_json_s;
// -----------------------------------------------------------------------------
// --SECTION-- REST_VOCBASE_BASE_HANDLER
// --SECTION-- class RestVocbaseBaseHandler
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
@ -342,23 +342,18 @@ namespace triagens {
// --SECTION-- Handler methods
// -----------------------------------------------------------------------------
public:
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup ArangoDB
/// @{
////////////////////////////////////////////////////////////////////////////////
public:
////////////////////////////////////////////////////////////////////////////////
/// {@inheritDoc}
////////////////////////////////////////////////////////////////////////////////
bool isDirect ();
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
};
}
}

View File

@ -56,6 +56,7 @@
#include "HttpServer/RedirectHandler.h"
#include "Logger/Logger.h"
#include "Rest/Initialise.h"
#include "RestHandler/RequestStatisticsHandler.h"
#include "RestHandler/RestBatchHandler.h"
#include "RestHandler/RestDocumentHandler.h"
#include "RestHandler/RestEdgeHandler.h"
@ -153,6 +154,10 @@ static void DefineAdminHandlers (HttpHandlerFactory* factory,
admin->addHandlers(factory, "/_admin");
user->addHandlers(factory, "/_admin");
// add statistics
factory->addHandler("/_admin/statistics",
RestHandlerCreator<RequestStatisticsHandler>::createNoData,
0);
}
////////////////////////////////////////////////////////////////////////////////

View File

@ -112,10 +112,10 @@ HttpHandler::status_e RestVersionHandler::execute () {
char const* valueStr = _request->value("sleep", found);
if (found) {
int32_t s = TRI_Int32String(valueStr);
double s = TRI_DoubleString(valueStr);
if (0 < s) {
sleep(s);
usleep(s * 1000.0 * 1000.0);
}
}
}

View File

@ -34,6 +34,11 @@
#include "Basics/Mutex.h"
#include "Basics/MutexLocker.h"
#include "Variant/VariantArray.h"
#include "Variant/VariantDouble.h"
#include "Variant/VariantUInt32.h"
#include "Variant/VariantUInt64.h"
#include "Variant/VariantVector.h"
// -----------------------------------------------------------------------------
// --SECTION-- public macros
@ -53,6 +58,9 @@
static triagens::basics::RrfCounter& access (S& s) { \
return s.n; \
} \
static triagens::basics::RrfCounter const& access (S const& s) { \
return s.n; \
} \
}; \
\
triagens::basics::RrfCounter n
@ -66,6 +74,9 @@
static triagens::basics::RrfContinuous& access (S& s) { \
return s.n; \
} \
static triagens::basics::RrfContinuous const& access (S const& s) { \
return s.n; \
} \
}; \
\
triagens::basics::RrfContinuous n
@ -81,6 +92,9 @@
static triagens::basics::RrfFigure& access (S& s) { \
return s.n; \
} \
static triagens::basics::RrfFigure const& access (S const& s) { \
return s.n; \
} \
}; \
\
triagens::basics::RrfFigure n
@ -96,6 +110,9 @@
static triagens::basics::RrfFigures<N>& access (S& s) { \
return s.n; \
} \
static triagens::basics::RrfFigures<N> const& access (S const& s) { \
return s.n; \
} \
}; \
\
triagens::basics::RrfFigures<N> n
@ -107,19 +124,22 @@
/// squares, the count, and minimum and maximum.
////////////////////////////////////////////////////////////////////////////////
#define RRF_DISTRIBUTION(S, n, a) \
struct n ## Cuts_s { \
static vector<double> cuts () { \
triagens::basics::RrfVector g; g << a; return g._value; \
} \
}; \
\
struct n ## Accessor { \
static triagens::basics::RrfDistribution<n ## Cuts_s>& access (S& s) { \
return s.n; \
} \
}; \
\
#define RRF_DISTRIBUTION(S, n, a) \
struct n ## Cuts_s { \
static std::vector<double> cuts () { \
triagens::basics::RrfVector g; g << a; return g._value; \
} \
}; \
\
struct n ## Accessor { \
static triagens::basics::RrfDistribution<n ## Cuts_s>& access (S& s) { \
return s.n; \
} \
static triagens::basics::RrfDistribution<n ## Cuts_s> const& access (S const& s) { \
return s.n; \
} \
}; \
\
triagens::basics::RrfDistribution<n ## Cuts_s> n
////////////////////////////////////////////////////////////////////////////////
@ -131,7 +151,7 @@
#define RRF_DISTRIBUTIONS(S, N, n, a) \
struct n ## Cuts_s { \
static vector<double> cuts () { \
static std::vector<double> cuts () { \
triagens::basics::RrfVector g; g << a; return g._value; \
} \
}; \
@ -173,7 +193,7 @@ namespace triagens {
return *this;
}
vector<double> _value;
std::vector<double> _value;
};
@ -289,8 +309,8 @@ namespace triagens {
double _squares;
double _minimum;
double _maximum;
vector<double> _cuts;
vector<uint32_t> _counts;
std::vector<double> _cuts;
std::vector<uint32_t> _counts;
};
////////////////////////////////////////////////////////////////////////////////
@ -326,14 +346,166 @@ namespace triagens {
double _squares[N];
double _minimum[N];
double _maximum[N];
vector<double> _cuts;
vector<uint32_t> _counts[N];
std::vector<double> _cuts;
std::vector<uint32_t> _counts[N];
};
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- public functions
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup Utilities
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief generates a variant representation for the distribution
////////////////////////////////////////////////////////////////////////////////
template<typename ACC, typename STAT>
void RRF_GenerateVariantDistribution (VariantArray* result,
STAT const& s,
std::string const& name) {
VariantArray* values = new VariantArray();
result->add(name, values);
VariantVector* cuts = new VariantVector();
values->add("cuts", cuts);
// generate the cuts
std::vector<double> const& vv = ACC::access(s)._cuts;
for (std::vector<double>::const_iterator k = vv.begin(); k != vv.end(); ++k) {
cuts->add(new VariantDouble(*k));
}
// generate the distribution values
uint32_t count = ACC::access(s)._count;
double sum = ACC::access(s)._sum;
double squares = ACC::access(s)._squares;
VariantUInt32* valCount = new VariantUInt32(count);
values->add("count", valCount);
VariantDouble* valMean = new VariantDouble(count == 0 ? 0.0 : (sum / count));
values->add("mean", valMean);
double w = 0;
if (1 < count) {
try {
w = sqrt(squares - sum * sum / count) / (count - 1);
}
catch (...) {
}
}
VariantDouble* valDeviation = new VariantDouble(w);
values->add("deviation", valDeviation);
VariantDouble* valMin = new VariantDouble(ACC::access(s)._minimum);
values->add("min", valMin);
VariantDouble* valMax = new VariantDouble(ACC::access(s)._maximum);
values->add("max", valMax);
VariantVector* dists = new VariantVector();
values->add("distribution", dists);
for (vector<uint32_t>::const_iterator m = ACC::access(s)._counts.begin(); m != ACC::access(s)._counts.end(); ++m) {
dists->add(new VariantUInt32(*m));
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief generates a variant representation for the distributions
////////////////////////////////////////////////////////////////////////////////
template<typename ACC, typename STAT>
void RRF_GenerateVariantDistributions (VariantArray* result,
typename std::vector<STAT> const& v,
std::string const& name) {
VariantArray* values = new VariantArray();
result->add(name, values);
VariantVector* cuts = new VariantVector();
values->add("cuts", cuts);
if (! v.empty()) {
// generate the cuts
{
STAT const& s = *(v.begin());
std::vector<double> const& vv = ACC::access(s)._cuts;
for (std::vector<double>::const_iterator k = vv.begin(); k != vv.end(); ++k) {
cuts->add(new VariantDouble(*k));
}
}
// generate the distribution values
VariantVector* vecCount = new VariantVector();
values->add("count", vecCount);
VariantVector* vecMean = new VariantVector();
values->add("mean", vecMean);
VariantVector* vecMin = new VariantVector();
values->add("min", vecMin);
VariantVector* vecMax = new VariantVector();
values->add("max", vecMax);
VariantVector* vecDeviation = new VariantVector();
values->add("deviation", vecDeviation);
VariantVector* vecDistribution = new VariantVector();
values->add("distribution", vecDistribution);
for (typename std::vector<STAT>::const_iterator j = v.begin(); j != v.end(); ++j) {
STAT const& s = *j;
uint32_t count = ACC::access(s)._count;
double sum = ACC::access(s)._sum;
double squares = ACC::access(s)._squares;
vecCount->add(new VariantUInt32(count));
vecMean->add(new VariantDouble(count == 0 ? 0.0 : (sum / count)));
double w = 0;
if (1 < count) {
try {
w = sqrt(squares - sum * sum / count) / (count - 1);
}
catch (...) {
}
}
vecDeviation->add(new VariantDouble(w));
vecMin->add(new VariantDouble(ACC::access(s)._minimum));
vecMax->add(new VariantDouble(ACC::access(s)._maximum));
VariantVector* dists = new VariantVector();
vecDistribution->add(dists);
for (vector<uint32_t>::const_iterator m = ACC::access(s)._counts.begin(); m != ACC::access(s)._counts.end(); ++m) {
dists->add(new VariantUInt32(*m));
}
}
}
}
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- class RoundRobinFigures
// -----------------------------------------------------------------------------
@ -349,7 +521,6 @@ namespace triagens {
template<size_t P, size_t N, typename S>
class RoundRobinFigures {
public:
////////////////////////////////////////////////////////////////////////////////
/// @}
@ -364,12 +535,12 @@ namespace triagens {
/// @{
////////////////////////////////////////////////////////////////////////////////
public:
////////////////////////////////////////////////////////////////////////////////
/// @brief constructor
////////////////////////////////////////////////////////////////////////////////
#ifdef TRI_ENABLE_FIGURES
RoundRobinFigures ()
: _current(0), _accessLock() {
for (size_t i = 0; i < N; ++i) {
@ -383,13 +554,6 @@ namespace triagens {
_start[_current] = (now / P) * P;
}
#else
RoundRobinFigures () {
}
#endif
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
@ -411,7 +575,6 @@ namespace triagens {
template<typename C>
void incCounter () {
#ifdef TRI_ENABLE_FIGURES
MUTEX_LOCKER(_accessLock);
checkTime();
@ -419,7 +582,6 @@ namespace triagens {
S& s = _buffer[_current];
C::access(s)._count += 1;
#endif
}
////////////////////////////////////////////////////////////////////////////////
@ -428,7 +590,6 @@ namespace triagens {
template<typename C>
void decCounter () {
#ifdef TRI_ENABLE_FIGURES
MUTEX_LOCKER(_accessLock);
checkTime();
@ -436,7 +597,6 @@ namespace triagens {
S& s = _buffer[_current];
C::access(s)._count -= 1;
#endif
}
////////////////////////////////////////////////////////////////////////////////
@ -445,7 +605,6 @@ namespace triagens {
template<typename F>
void addFigure (double value) {
#ifdef TRI_ENABLE_FIGURES
MUTEX_LOCKER(_accessLock);
checkTime();
@ -454,7 +613,6 @@ namespace triagens {
F::access(s)._count += 1;
F::access(s)._sum += value;
#endif
}
////////////////////////////////////////////////////////////////////////////////
@ -463,7 +621,6 @@ namespace triagens {
template<typename F>
void addFigure (size_t pos, double value) {
#ifdef TRI_ENABLE_FIGURES
MUTEX_LOCKER(_accessLock);
checkTime();
@ -472,7 +629,6 @@ namespace triagens {
F::access(s)._count[pos] += 1;
F::access(s)._sum[pos] += value;
#endif
}
////////////////////////////////////////////////////////////////////////////////
@ -481,7 +637,6 @@ namespace triagens {
template<typename F>
void addDistribution (double value) {
#ifdef TRI_ENABLE_FIGURES
MUTEX_LOCKER(_accessLock);
checkTime();
@ -500,8 +655,8 @@ namespace triagens {
F::access(s)._maximum = value;
}
typename vector<double>::const_iterator i = F::access(s)._cuts.begin();
vector<uint32_t>::iterator j = F::access(s)._counts.begin();
typename std::vector<double>::const_iterator i = F::access(s)._cuts.begin();
std::vector<uint32_t>::iterator j = F::access(s)._counts.begin();
for(; i != F::access(s)._cuts.end(); ++i, ++j) {
if (value < *i) {
@ -511,7 +666,6 @@ namespace triagens {
}
(*j)++;
#endif
}
////////////////////////////////////////////////////////////////////////////////
@ -520,7 +674,6 @@ namespace triagens {
template<typename F>
void addDistribution (size_t pos, double value) {
#ifdef TRI_ENABLE_FIGURES
MUTEX_LOCKER(_accessLock);
checkTime();
@ -539,8 +692,8 @@ namespace triagens {
F::access(s)._maximum[pos] = value;
}
typename vector<double>::const_iterator i = F::access(s)._cuts.begin();
vector<uint32_t>::iterator j = F::access(s)._counts[pos].begin();
typename std::vector<double>::const_iterator i = F::access(s)._cuts.begin();
std::vector<uint32_t>::iterator j = F::access(s)._counts[pos].begin();
for(; i != F::access(s)._cuts.end(); ++i, ++j) {
if (value < *i) {
@ -550,17 +703,15 @@ namespace triagens {
}
(*j)++;
#endif
}
////////////////////////////////////////////////////////////////////////////////
/// @brief returns the list of distributions
////////////////////////////////////////////////////////////////////////////////
vector<S> values (size_t n = N) {
vector<S> result;
std::vector<S> values (size_t n = N) {
std::vector<S> result;
#ifdef TRI_ENABLE_FIGURES
MUTEX_LOCKER(_accessLock);
checkTime();
@ -576,8 +727,6 @@ namespace triagens {
j = (j + 1) % N;
}
#endif
return result;
}
@ -585,10 +734,9 @@ namespace triagens {
/// @brief returns the list of distributions and times
////////////////////////////////////////////////////////////////////////////////
vector<S> values (vector<time_t>& times, size_t n = N) {
vector<S> result;
std::vector<S> values (vector<time_t>& times, size_t n = N) {
std::vector<S> result;
#ifdef TRI_ENABLE_FIGURES
MUTEX_LOCKER(_accessLock);
checkTime();
@ -606,11 +754,39 @@ namespace triagens {
times.push_back(_start[j]);
j = (j + 1) % N;
}
#endif
return result;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief returns the resolution
////////////////////////////////////////////////////////////////////////////////
size_t getResolution () const {
return P;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief returns the length
////////////////////////////////////////////////////////////////////////////////
size_t getLength () const {
return N;
}
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- protected methods
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup Utilities
/// @{
////////////////////////////////////////////////////////////////////////////////
protected:
////////////////////////////////////////////////////////////////////////////////
@ -618,7 +794,6 @@ namespace triagens {
////////////////////////////////////////////////////////////////////////////////
void checkTime () {
#ifdef TRI_ENABLE_FIGURES
time_t now = time(0);
size_t p1 = now / P;
@ -636,7 +811,6 @@ namespace triagens {
_buffer[_current] = save;
_start[_current] = p * P;
}
#endif
}
////////////////////////////////////////////////////////////////////////////////
@ -658,33 +832,25 @@ namespace triagens {
/// @brief staticstics ring-buffer
////////////////////////////////////////////////////////////////////////////////
#ifdef TRI_ENABLE_FIGURES
S _buffer[N];
#endif
////////////////////////////////////////////////////////////////////////////////
/// @brief time buffer
////////////////////////////////////////////////////////////////////////////////
#ifdef TRI_ENABLE_FIGURES
time_t _start[N];
#endif
////////////////////////////////////////////////////////////////////////////////
/// @brief current position
////////////////////////////////////////////////////////////////////////////////
#ifdef TRI_ENABLE_FIGURES
size_t _current;
#endif
////////////////////////////////////////////////////////////////////////////////
/// @brief access lock
////////////////////////////////////////////////////////////////////////////////
#ifdef TRI_ENABLE_FIGURES
Mutex _accessLock;
#endif
};
}
}

View File

@ -80,7 +80,7 @@ lib_libarango_a_SOURCES = \
lib/ShapedJson/json-shaper.c \
lib/ShapedJson/shape-accessor.c \
lib/ShapedJson/shaped-json.c \
lib/Statistics/request-statistics.c \
lib/Statistics/request-statistics.cpp \
lib/Statistics/statistics.c \
lib/Utilities/LineEditor.cpp \
lib/Utilities/ScriptLoader.cpp \

View File

@ -67,10 +67,6 @@ namespace {
LOGGER_INFO << "control-c received, beginning shut down sequence";
_server->beginShutdown();
}
else if (_seen == 1) {
LOGGER_INFO << "control-c received, shutting down";
_server->stop();
}
else {
LOGGER_INFO << "control-c received, terminating";
exit(EXIT_FAILURE);

View File

@ -1,206 +0,0 @@
////////////////////////////////////////////////////////////////////////////////
/// @brief request statistics
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2004-2012 triAGENS GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is triAGENS GmbH, Cologne, Germany
///
/// @author Dr. Frank Celler
/// @author Copyright 2012, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////
#include "request-statistics.h"
#include "BasicsC/locks.h"
#ifdef TRI_USE_SPIN_LOCK_STATISTICS
#define STATISTICS_INIT TRI_InitSpin
#define STATISTICS_DESTROY TRI_DestroySpin
#define STATISTICS_LOCK TRI_LockSpin
#define STATISTICS_UNLOCK TRI_UnlockSpin
#else
#define STATISTICS_INIT TRI_InitMutex
#define STATISTICS_DESTROY TRI_DestroyMutex
#define STATISTICS_LOCK TRI_LockMutex
#define STATISTICS_UNLOCK TRI_UnlockMutex
#endif
// -----------------------------------------------------------------------------
// --SECTION-- private variables
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup Statistics
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief lock for lists
////////////////////////////////////////////////////////////////////////////////
#ifdef TRI_USE_SPIN_LOCK_STATISTICS
static TRI_spin_t ListLock;
#else
static TRI_mutex_t ListLock;
#endif
////////////////////////////////////////////////////////////////////////////////
/// @brief free list
////////////////////////////////////////////////////////////////////////////////
static TRI_statistics_list_t FreeList;
////////////////////////////////////////////////////////////////////////////////
/// @brief dirty list
////////////////////////////////////////////////////////////////////////////////
static TRI_statistics_list_t DirtyList;
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- public functions
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup Statistics
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief gets a new statistics block
////////////////////////////////////////////////////////////////////////////////
TRI_request_statistics_t* TRI_AcquireRequestStatistics () {
TRI_request_statistics_t* statistics = 0;
STATISTICS_LOCK(&ListLock);
if (FreeList._first != NULL) {
statistics = (TRI_request_statistics_t*) FreeList._first;
FreeList._first = FreeList._first->_next;
}
else if (DirtyList._first != NULL) {
statistics = (TRI_request_statistics_t*) DirtyList._first;
DirtyList._first = DirtyList._first->_next;
}
STATISTICS_UNLOCK(&ListLock);
return statistics;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief releases a statistics block
////////////////////////////////////////////////////////////////////////////////
void TRI_ReleaseRequestStatistics (TRI_request_statistics_t* statistics) {
STATISTICS_LOCK(&ListLock);
if (DirtyList._first == NULL) {
DirtyList._first = (TRI_statistics_entry_t*) statistics;
DirtyList._last = (TRI_statistics_entry_t*) statistics;
}
else {
DirtyList._last->_next = (TRI_statistics_entry_t*) statistics;
DirtyList._last = (TRI_statistics_entry_t*) statistics;
}
DirtyList._last->_next = 0;
STATISTICS_UNLOCK(&ListLock);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief updates the request statistics
////////////////////////////////////////////////////////////////////////////////
void TRI_UpdateRequestStatistics (double now) {
TRI_request_statistics_t* statistics ;
STATISTICS_LOCK(&ListLock);
while (DirtyList._first != NULL) {
statistics = (TRI_request_statistics_t*) DirtyList._first;
DirtyList._first = DirtyList._first->_next;
STATISTICS_UNLOCK(&ListLock);
printf("================================================================================\n");
printf("read start: %f\n", statistics->_readStart);
printf("read end: %f\n", statistics->_readEnd);
printf("queue start: %f\n", statistics->_queueStart);
printf("queue end: %f\n", statistics->_queueEnd);
printf("request start: %f\n", statistics->_requestStart);
printf("request end: %f\n", statistics->_requestEnd);
printf("write start: %f\n", statistics->_writeStart);
printf("write end: %f\n", statistics->_writeEnd);
printf("bytes received: %f\n", statistics->_receivedBytes);
printf("bytes sent: %f\n", statistics->_sentBytes);
printf("too large: %s\n", statistics->_tooLarge ? "yes" : "no");
printf("execute error: %s\n", statistics->_executeError ? "yes" : "no");
STATISTICS_LOCK(&ListLock);
if (FreeList._first == NULL) {
FreeList._first = (TRI_statistics_entry_t*) statistics;
FreeList._last = (TRI_statistics_entry_t*) statistics;
}
else {
FreeList._last->_next = (TRI_statistics_entry_t*) statistics;
FreeList._last = (TRI_statistics_entry_t*) statistics;
}
}
STATISTICS_UNLOCK(&ListLock);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief module init function
////////////////////////////////////////////////////////////////////////////////
void TRI_InitialiseRequestStatistics () {
static size_t const QUEUE_SIZE = 1000;
FreeList._first = FreeList._last = NULL;
DirtyList._first = DirtyList._last = NULL;
TRI_FillStatisticsList(&FreeList, sizeof(TRI_request_statistics_t), QUEUE_SIZE);
STATISTICS_INIT(&ListLock);
}
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- END-OF-FILE
// -----------------------------------------------------------------------------
// Local Variables:
// mode: outline-minor
// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|/// @page\\|// --SECTION--\\|/// @\\}\\)"
// End:

View File

@ -0,0 +1,464 @@
////////////////////////////////////////////////////////////////////////////////
/// @brief request statistics
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2004-2012 triAGENS GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is triAGENS GmbH, Cologne, Germany
///
/// @author Dr. Frank Celler
/// @author Copyright 2012, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////
#include "request-statistics.h"
#include "Basics/MutexLocker.h"
#include "Basics/RoundRobinFigures.h"
#include "Basics/StringBuffer.h"
#include "BasicsC/locks.h"
#include "ResultGenerator/JsonResultGenerator.h"
#include "Variant/VariantArray.h"
#include "Variant/VariantVector.h"
using namespace triagens::basics;
using namespace triagens::rest;
using namespace std;
#ifdef TRI_USE_SPIN_LOCK_STATISTICS
#define STATISTICS_INIT TRI_InitSpin
#define STATISTICS_DESTROY TRI_DestroySpin
#define STATISTICS_LOCK TRI_LockSpin
#define STATISTICS_UNLOCK TRI_UnlockSpin
#else
#define STATISTICS_INIT TRI_InitMutex
#define STATISTICS_DESTROY TRI_DestroyMutex
#define STATISTICS_LOCK TRI_LockMutex
#define STATISTICS_UNLOCK TRI_UnlockMutex
#endif
// -----------------------------------------------------------------------------
// --SECTION-- private types
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup Statistics
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief request statistics description
////////////////////////////////////////////////////////////////////////////////
struct RequestStatisticsDesc {
RRF_DISTRIBUTION(RequestStatisticsDesc,
total,
(0.0001) << (0.01) << (0.05) << (0.1) << (0.2) << (0.5) << (1.0));
RRF_DISTRIBUTION(RequestStatisticsDesc,
queue,
(0.0001) << (0.01) << (0.05) << (0.1) << (0.2) << (0.5) << (1.0));
RRF_DISTRIBUTION(RequestStatisticsDesc,
request,
(0.0001) << (0.01) << (0.05) << (0.1) << (0.2) << (0.5) << (1.0));
RRF_DISTRIBUTION(RequestStatisticsDesc,
bytesSent,
(250) << (1000) << (2 * 1000) << (5 * 1000) << (10 * 1000));
RRF_DISTRIBUTION(RequestStatisticsDesc,
bytesReceived,
(250) << (1000) << (2 * 1000) << (5 * 1000) << (10 * 1000));
};
////////////////////////////////////////////////////////////////////////////////
/// @brief request statistics figures
////////////////////////////////////////////////////////////////////////////////
struct RequestStatisticsFigures {
Mutex _lock;
triagens::basics::RoundRobinFigures<60, 120, RequestStatisticsDesc> _minute;
triagens::basics::RoundRobinFigures<60 * 60, 48, RequestStatisticsDesc> _hour;
triagens::basics::RoundRobinFigures<24 * 60 * 60, 5, RequestStatisticsDesc> _day;
};
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- private variables
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup Statistics
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief request statistics figures
////////////////////////////////////////////////////////////////////////////////
static RequestStatisticsFigures RequestStatistics;
////////////////////////////////////////////////////////////////////////////////
/// @brief lock for lists
////////////////////////////////////////////////////////////////////////////////
#ifdef TRI_USE_SPIN_LOCK_STATISTICS
static TRI_spin_t ListLock;
#else
static TRI_mutex_t ListLock;
#endif
////////////////////////////////////////////////////////////////////////////////
/// @brief free list
////////////////////////////////////////////////////////////////////////////////
static TRI_statistics_list_t FreeList;
////////////////////////////////////////////////////////////////////////////////
/// @brief dirty list
////////////////////////////////////////////////////////////////////////////////
static TRI_statistics_list_t DirtyList;
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- public functions
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup Statistics
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief gets a new statistics block
////////////////////////////////////////////////////////////////////////////////
TRI_request_statistics_t* TRI_AcquireRequestStatistics () {
TRI_request_statistics_t* statistics = 0;
STATISTICS_LOCK(&ListLock);
if (FreeList._first != NULL) {
statistics = (TRI_request_statistics_t*) FreeList._first;
FreeList._first = FreeList._first->_next;
}
else if (DirtyList._first != NULL) {
statistics = (TRI_request_statistics_t*) DirtyList._first;
DirtyList._first = DirtyList._first->_next;
memset(statistics, 0, sizeof(TRI_request_statistics_t));
}
STATISTICS_UNLOCK(&ListLock);
return statistics;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief releases a statistics block
////////////////////////////////////////////////////////////////////////////////
void TRI_ReleaseRequestStatistics (TRI_request_statistics_t* statistics) {
STATISTICS_LOCK(&ListLock);
if (DirtyList._first == NULL) {
DirtyList._first = (TRI_statistics_entry_t*) statistics;
DirtyList._last = (TRI_statistics_entry_t*) statistics;
}
else {
DirtyList._last->_next = (TRI_statistics_entry_t*) statistics;
DirtyList._last = (TRI_statistics_entry_t*) statistics;
}
DirtyList._last->_next = 0;
STATISTICS_UNLOCK(&ListLock);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief updates the request statistics
////////////////////////////////////////////////////////////////////////////////
void TRI_UpdateRequestStatistics (double now) {
TRI_request_statistics_t* statistics ;
STATISTICS_LOCK(&ListLock);
while (DirtyList._first != NULL) {
statistics = (TRI_request_statistics_t*) DirtyList._first;
DirtyList._first = DirtyList._first->_next;
STATISTICS_UNLOCK(&ListLock);
// check the request was completely received and transmitted
if (statistics->_readStart != 0.0 && statistics->_writeEnd != 0.0) {
MUTEX_LOCKER(RequestStatistics._lock);
double totalTime = statistics->_writeEnd - statistics->_readStart;
RequestStatistics._minute.addDistribution<RequestStatisticsDesc::totalAccessor>(totalTime);
RequestStatistics._hour.addDistribution<RequestStatisticsDesc::totalAccessor>(totalTime);
RequestStatistics._day.addDistribution<RequestStatisticsDesc::totalAccessor>(totalTime);
double requestTime = statistics->_requestEnd - statistics->_requestStart;
RequestStatistics._minute.addDistribution<RequestStatisticsDesc::requestAccessor>(requestTime);
RequestStatistics._hour.addDistribution<RequestStatisticsDesc::requestAccessor>(requestTime);
RequestStatistics._day.addDistribution<RequestStatisticsDesc::requestAccessor>(requestTime);
if (statistics->_queueStart != 0.0 && statistics->_queueEnd != 0.0) {
double queueTime = statistics->_queueEnd - statistics->_queueStart;
RequestStatistics._minute.addDistribution<RequestStatisticsDesc::queueAccessor>(queueTime);
RequestStatistics._hour.addDistribution<RequestStatisticsDesc::queueAccessor>(queueTime);
RequestStatistics._day.addDistribution<RequestStatisticsDesc::queueAccessor>(queueTime);
}
RequestStatistics._minute.addDistribution<RequestStatisticsDesc::bytesSentAccessor>(statistics->_sentBytes);
RequestStatistics._hour.addDistribution<RequestStatisticsDesc::bytesSentAccessor>(statistics->_sentBytes);
RequestStatistics._day.addDistribution<RequestStatisticsDesc::bytesSentAccessor>(statistics->_sentBytes);
RequestStatistics._minute.addDistribution<RequestStatisticsDesc::bytesReceivedAccessor>(statistics->_receivedBytes);
RequestStatistics._hour.addDistribution<RequestStatisticsDesc::bytesReceivedAccessor>(statistics->_receivedBytes);
RequestStatistics._day.addDistribution<RequestStatisticsDesc::bytesReceivedAccessor>(statistics->_receivedBytes);
}
// clear the old data
memset(statistics, 0, sizeof(TRI_request_statistics_t));
// put statistic block back onto the free list
STATISTICS_LOCK(&ListLock);
if (FreeList._first == NULL) {
FreeList._first = (TRI_statistics_entry_t*) statistics;
FreeList._last = (TRI_statistics_entry_t*) statistics;
}
else {
FreeList._last->_next = (TRI_statistics_entry_t*) statistics;
FreeList._last = (TRI_statistics_entry_t*) statistics;
}
}
STATISTICS_UNLOCK(&ListLock);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief returns a statistics list
////////////////////////////////////////////////////////////////////////////////
VariantArray* TRI_RequestStatistics (TRI_request_statistics_granularity_e granularity,
size_t limit,
bool showTotalTime,
bool showQueueTime,
bool showRequestTime,
bool showBytesSent,
bool showBytesReceived) {
vector<time_t> t;
vector<RequestStatisticsDesc> blocks;
// .............................................................................
// extract the statistics blocks for the given granularity
// .............................................................................
size_t resolution = 0;
size_t total = 0;
{
MUTEX_LOCKER(RequestStatistics._lock);
switch (granularity) {
case TRI_REQUEST_STATISTICS_SECONDS:
// not used/implemented, yet
break;
case TRI_REQUEST_STATISTICS_MINUTES:
resolution = RequestStatistics._minute.getResolution();
total = RequestStatistics._minute.getLength();
if (limit == (size_t) -1) {
blocks = RequestStatistics._minute.values(t);
}
else if (limit == 0) {
blocks = RequestStatistics._minute.values(t, 1);
}
else {
blocks = RequestStatistics._minute.values(t, limit);
}
break;
case TRI_REQUEST_STATISTICS_HOURS:
resolution = RequestStatistics._hour.getResolution();
total = RequestStatistics._hour.getLength();
if (limit == (size_t) -1) {
blocks = RequestStatistics._hour.values(t);
}
else if (limit == 0) {
blocks = RequestStatistics._hour.values(t, 1);
}
else {
blocks = RequestStatistics._hour.values(t, limit);
}
break;
case TRI_REQUEST_STATISTICS_DAYS:
resolution = RequestStatistics._day.getResolution();
total = RequestStatistics._day.getLength();
if (limit == (size_t) -1) {
blocks = RequestStatistics._day.values(t);
}
else if (limit == 0) {
blocks = RequestStatistics._day.values(t, 1);
}
else {
blocks = RequestStatistics._day.values(t, limit);
}
break;
}
}
// .............................................................................
// CASE 1: generate the current aka last block only
// .............................................................................
VariantArray* result = new VariantArray();
result->add("resolution", new VariantUInt64(resolution));
if (blocks.empty()) {
return result;
}
if (limit == 0) {
result->add("start", new VariantUInt32((uint32_t) t[0]));
if (showTotalTime) {
RRF_GenerateVariantDistribution<RequestStatisticsDesc::totalAccessor>(result, blocks[0], "totalTime");
}
if (showQueueTime) {
RRF_GenerateVariantDistribution<RequestStatisticsDesc::queueAccessor>(result, blocks[0], "queueTime");
}
if (showRequestTime) {
RRF_GenerateVariantDistribution<RequestStatisticsDesc::requestAccessor>(result, blocks[0], "requestTime");
}
if (showBytesSent) {
RRF_GenerateVariantDistribution<RequestStatisticsDesc::bytesSentAccessor>(result, blocks[0], "bytesSent");
}
if (showBytesReceived) {
RRF_GenerateVariantDistribution<RequestStatisticsDesc::bytesReceivedAccessor>(result, blocks[0], "bytesReceived");
}
}
// .............................................................................
// CASE 2: generate all blocks upto limit
// .............................................................................
else {
VariantVector* start = new VariantVector();
result->add("start", start);
size_t offset = 0;
std::vector<time_t>::const_iterator k = t.begin();
for (; k != t.end(); ++k, ++offset) {
if (*k != 0) {
break;
}
}
for (; k != t.end(); ++k) {
start->add(new VariantUInt32(*k));
}
if (0 < offset) {
vector<RequestStatisticsDesc> tmp;
tmp.insert(tmp.begin(), blocks.begin() + offset, blocks.end());
blocks.swap(tmp);
}
result->add("length", new VariantUInt64(blocks.size()));;
result->add("totalLength", new VariantUInt64(total));
if (showTotalTime) {
RRF_GenerateVariantDistributions<RequestStatisticsDesc::totalAccessor>(result, blocks, "totalTime");
}
if (showQueueTime) {
RRF_GenerateVariantDistributions<RequestStatisticsDesc::queueAccessor>(result, blocks, "queueTime");
}
if (showRequestTime) {
RRF_GenerateVariantDistributions<RequestStatisticsDesc::requestAccessor>(result, blocks, "requestTime");
}
if (showBytesSent) {
RRF_GenerateVariantDistributions<RequestStatisticsDesc::bytesSentAccessor>(result, blocks, "bytesSent");
}
if (showBytesReceived) {
RRF_GenerateVariantDistributions<RequestStatisticsDesc::bytesReceivedAccessor>(result, blocks, "bytesReceived");
}
}
return result;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief module init function
////////////////////////////////////////////////////////////////////////////////
void TRI_InitialiseRequestStatistics () {
static size_t const QUEUE_SIZE = 1000;
FreeList._first = FreeList._last = NULL;
DirtyList._first = DirtyList._last = NULL;
TRI_FillStatisticsList(&FreeList, sizeof(TRI_request_statistics_t), QUEUE_SIZE);
STATISTICS_INIT(&ListLock);
}
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- END-OF-FILE
// -----------------------------------------------------------------------------
// Local Variables:
// mode: outline-minor
// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|/// @page\\|// --SECTION--\\|/// @\\}\\)"
// End:

View File

@ -30,6 +30,20 @@
#include "Statistics/statistics.h"
// -----------------------------------------------------------------------------
// --SECTION-- forward declarations
// -----------------------------------------------------------------------------
#ifdef __cplusplus
namespace triagens {
namespace basics {
class VariantArray;
}
}
#endif
#ifdef __cplusplus
extern "C" {
#endif
@ -43,6 +57,17 @@ extern "C" {
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief request granularity
////////////////////////////////////////////////////////////////////////////////
enum TRI_request_statistics_granularity_e {
TRI_REQUEST_STATISTICS_SECONDS,
TRI_REQUEST_STATISTICS_MINUTES,
TRI_REQUEST_STATISTICS_HOURS,
TRI_REQUEST_STATISTICS_DAYS
};
////////////////////////////////////////////////////////////////////////////////
/// @brief request statistics
////////////////////////////////////////////////////////////////////////////////
@ -98,6 +123,22 @@ void TRI_ReleaseRequestStatistics (TRI_request_statistics_t*);
void TRI_UpdateRequestStatistics (double now);
////////////////////////////////////////////////////////////////////////////////
/// @brief returns a statistics list
////////////////////////////////////////////////////////////////////////////////
#ifdef __cplusplus
triagens::basics::VariantArray* TRI_RequestStatistics (TRI_request_statistics_granularity_e granularity,
size_t limit,
bool showTotalTime,
bool showQueueTime,
bool showRequestTime,
bool showBytesSent,
bool showBytesReceived);
#endif
////////////////////////////////////////////////////////////////////////////////
/// @brief module init function
////////////////////////////////////////////////////////////////////////////////

View File

@ -32,8 +32,8 @@
#include "Statistics/request-statistics.h"
// #define TRI_USE_TIME_FIGURES 1
#define TRI_USE_CLOCK_GETTIME_FIGURES 1
// #define TRI_USE_THREAD_TIME 1
// #define TRI_USE_CLOCK_GETTIME_FIGURES 1
#define TRI_USE_THREAD_TIME 1
// -----------------------------------------------------------------------------
// --SECTION-- private variables