diff --git a/arangod/Aql/ExecutionBlock.cpp b/arangod/Aql/ExecutionBlock.cpp index c1aefd5d67..6754752434 100644 --- a/arangod/Aql/ExecutionBlock.cpp +++ b/arangod/Aql/ExecutionBlock.cpp @@ -4536,6 +4536,12 @@ AqlItemBlock* RemoteBlock::getSome (size_t atLeast, } auto items = new triagens::aql::AqlItemBlock(responseBodyJson); + + ExecutionStats newStats(responseBodyJson.get("stats")); + + _engine->_stats.addDelta(_deltaStats, newStats); + _deltaStats = newStats; + return items; } diff --git a/arangod/Aql/ExecutionBlock.h b/arangod/Aql/ExecutionBlock.h index c4e6cc66ca..f4b5ed4951 100644 --- a/arangod/Aql/ExecutionBlock.h +++ b/arangod/Aql/ExecutionBlock.h @@ -36,6 +36,7 @@ #include "Aql/ExecutionNode.h" #include "Aql/Range.h" #include "Aql/WalkerWorker.h" +#include "Aql/ExecutionStats.h" #include "Utils/AqlTransaction.h" #include "Utils/transactions.h" #include "Utils/V8TransactionContext.h" @@ -1930,6 +1931,13 @@ namespace triagens { std::string _queryId; +//////////////////////////////////////////////////////////////////////////////// +/// @brief the ID of the query on the server as a string +//////////////////////////////////////////////////////////////////////////////// + + ExecutionStats _deltaStats; + + }; } // namespace triagens::aql diff --git a/arangod/Aql/ExecutionStats.cpp b/arangod/Aql/ExecutionStats.cpp index 4b77af33be..0dadd9f702 100644 --- a/arangod/Aql/ExecutionStats.cpp +++ b/arangod/Aql/ExecutionStats.cpp @@ -28,9 +28,10 @@ //////////////////////////////////////////////////////////////////////////////// #include "Aql/ExecutionStats.h" - +#include "Utils/Exception.h" using namespace triagens::aql; using Json = triagens::basics::Json; +using JsonHelper = triagens::basics::JsonHelper; // ----------------------------------------------------------------------------- // --SECTION-- public methods @@ -50,6 +51,24 @@ Json ExecutionStats::toJson () const { return json; } +ExecutionStats::ExecutionStats() + :writesExecuted(0), + writesIgnored(0), + scannedFull(0), + scannedIndex(0) { +} + +ExecutionStats::ExecutionStats (triagens::basics::Json const& jsonStats) { + if (!jsonStats.isArray()) { + THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "stats is not an Array"); + } + + writesExecuted = JsonHelper::checkAndGetNumericValue(jsonStats.json(), "writesExecuted"); + writesIgnored = JsonHelper::checkAndGetNumericValue(jsonStats.json(), "writesIgnored"); + scannedFull = JsonHelper::checkAndGetNumericValue(jsonStats.json(), "scannedFull"); + scannedIndex = JsonHelper::checkAndGetNumericValue(jsonStats.json(), "scannedIndex"); +} + // ----------------------------------------------------------------------------- // --SECTION-- END-OF-FILE // ----------------------------------------------------------------------------- diff --git a/arangod/Aql/ExecutionStats.h b/arangod/Aql/ExecutionStats.h index 36a86c7c1b..733deb177f 100644 --- a/arangod/Aql/ExecutionStats.h +++ b/arangod/Aql/ExecutionStats.h @@ -38,35 +38,66 @@ namespace triagens { struct ExecutionStats { + ExecutionStats (); + +//////////////////////////////////////////////////////////////////////////////// +/// @brief instanciate the statistics from JSON +//////////////////////////////////////////////////////////////////////////////// + + ExecutionStats (triagens::basics::Json const& jsonStats); + //////////////////////////////////////////////////////////////////////////////// /// @brief convert the statistics to JSON //////////////////////////////////////////////////////////////////////////////// triagens::basics::Json toJson () const; +//////////////////////////////////////////////////////////////////////////////// +/// @brief sumarize two sets of ExecutionStats +//////////////////////////////////////////////////////////////////////////////// + + void add (ExecutionStats const& summand) { + writesExecuted += summand.writesExecuted; + writesIgnored += summand.writesIgnored; + scannedFull += summand.scannedFull; + scannedIndex += summand.scannedIndex; + } + +//////////////////////////////////////////////////////////////////////////////// +/// @brief sumarize the delta of two other sets of ExecutionStats to us +//////////////////////////////////////////////////////////////////////////////// + + void addDelta (ExecutionStats const& lastStats, ExecutionStats const& newStats) { + writesExecuted += newStats.writesExecuted - lastStats.writesExecuted; + writesIgnored += newStats.writesIgnored - lastStats.writesIgnored; + scannedFull += newStats.scannedFull - lastStats.scannedFull; + scannedIndex += newStats.scannedIndex - lastStats.scannedIndex; + } + + //////////////////////////////////////////////////////////////////////////////// /// @brief number of successfully executed write operations //////////////////////////////////////////////////////////////////////////////// - int64_t writesExecuted = 0; + int64_t writesExecuted; //////////////////////////////////////////////////////////////////////////////// /// @brief number of ignored write operations (ignored due to errors) //////////////////////////////////////////////////////////////////////////////// - int64_t writesIgnored = 0; + int64_t writesIgnored; //////////////////////////////////////////////////////////////////////////////// /// @brief number of documents scanned (full-collection scan) //////////////////////////////////////////////////////////////////////////////// - int64_t scannedFull = 0; + int64_t scannedFull; //////////////////////////////////////////////////////////////////////////////// /// @brief number of documents scanned (using indexes scan) //////////////////////////////////////////////////////////////////////////////// - int64_t scannedIndex = 0; + int64_t scannedIndex; }; diff --git a/arangod/Aql/Query.cpp b/arangod/Aql/Query.cpp index b4edb9b5c5..a23f0f96c2 100644 --- a/arangod/Aql/Query.cpp +++ b/arangod/Aql/Query.cpp @@ -858,6 +858,14 @@ void Query::exitContext () { } } +//////////////////////////////////////////////////////////////////////////////// +/// @brief returns statistics for current query. +//////////////////////////////////////////////////////////////////////////////// + +triagens::basics::Json Query::getStats() { + return _engine->_stats.toJson(); +} + //////////////////////////////////////////////////////////////////////////////// /// @brief fetch a boolean value from the options //////////////////////////////////////////////////////////////////////////////// diff --git a/arangod/Aql/Query.h b/arangod/Aql/Query.h index e3b56fa28a..ac7d35a0e3 100644 --- a/arangod/Aql/Query.h +++ b/arangod/Aql/Query.h @@ -380,6 +380,12 @@ namespace triagens { void exitContext (); +//////////////////////////////////////////////////////////////////////////////// +/// @brief returns statistics for current query. +//////////////////////////////////////////////////////////////////////////////// + + triagens::basics::Json getStats(); + // ----------------------------------------------------------------------------- // --SECTION-- private methods // ----------------------------------------------------------------------------- diff --git a/arangod/Aql/RestAqlHandler.cpp b/arangod/Aql/RestAqlHandler.cpp index bf334c153b..14e9b05265 100644 --- a/arangod/Aql/RestAqlHandler.cpp +++ b/arangod/Aql/RestAqlHandler.cpp @@ -743,6 +743,7 @@ void RestAqlHandler::handleUseQuery (std::string const& operation, else { try { answerBody = items->toJson(query->trx()); + answerBody.set("stats", query->getStats()); // std::cout << "ANSWERBODY: " << JsonHelper::toString(answerBody.json()) << "\n\n"; } catch (...) { diff --git a/lib/Basics/JsonHelper.h b/lib/Basics/JsonHelper.h index 1f55176c3d..11fad8b7e3 100644 --- a/lib/Basics/JsonHelper.h +++ b/lib/Basics/JsonHelper.h @@ -870,7 +870,7 @@ namespace triagens { /// @brief checks whether *this is a Json that is equal to null. //////////////////////////////////////////////////////////////////////////////// - bool isNull () throw() { + bool isNull () const throw() { return _json != nullptr && _json->_type == TRI_JSON_NULL; } @@ -878,7 +878,7 @@ namespace triagens { /// @brief checks whether *this is a boolean Json. //////////////////////////////////////////////////////////////////////////////// - bool isBoolean () throw() { + bool isBoolean () const throw() { return TRI_IsBooleanJson(_json); } @@ -886,7 +886,7 @@ namespace triagens { /// @brief checks whether *this is a number Json. //////////////////////////////////////////////////////////////////////////////// - bool isNumber () throw() { + bool isNumber () const throw() { return TRI_IsNumberJson(_json); } @@ -894,7 +894,7 @@ namespace triagens { /// @brief checks whether *this is a string Json. //////////////////////////////////////////////////////////////////////////////// - bool isString () throw() { + bool isString () const throw() { return TRI_IsStringJson(_json); } @@ -902,7 +902,7 @@ namespace triagens { /// @brief checks whether *this is an array Json. //////////////////////////////////////////////////////////////////////////////// - bool isArray () throw() { + bool isArray () const throw() { return TRI_IsArrayJson(_json); } @@ -910,7 +910,7 @@ namespace triagens { /// @brief checks whether *this is a list Json. //////////////////////////////////////////////////////////////////////////////// - bool isList () throw() { + bool isList () const throw() { return TRI_IsListJson(_json); } diff --git a/lib/V8/v8-utils.cpp b/lib/V8/v8-utils.cpp index 48fcfd5382..b64636a437 100644 --- a/lib/V8/v8-utils.cpp +++ b/lib/V8/v8-utils.cpp @@ -2838,7 +2838,7 @@ static v8::Handle JS_PBKDF2 (v8::Arguments const& argv) { // extract arguments if (argv.Length() < 4 || ! argv[0]->IsString() || ! argv[1]->IsString() || ! argv[2]->IsNumber() || ! argv[3]->IsNumber()) { - TRI_V8_EXCEPTION_USAGE(scope, "PBKDF2(, , , , )"); + TRI_V8_EXCEPTION_USAGE(scope, "PBKDF2(, , , )"); } string salt = TRI_ObjectToString(argv[0]);