From b98c4c2d5b2153e8ccd0a73bed46fc654352fb28 Mon Sep 17 00:00:00 2001 From: Jan Steemann Date: Thu, 12 Mar 2015 11:40:46 +0100 Subject: [PATCH] added documentation, fixed potential UTF-8 truncation --- .../Books/Users/HttpAqlQuery/README.mdpp | 23 ++++- arangod/Aql/QueryList.cpp | 32 +++++++ js/actions/api-query.js | 89 ++++++++++++++++++- 3 files changed, 142 insertions(+), 2 deletions(-) diff --git a/Documentation/Books/Users/HttpAqlQuery/README.mdpp b/Documentation/Books/Users/HttpAqlQuery/README.mdpp index 987a1888d9..3217cb3ce2 100644 --- a/Documentation/Books/Users/HttpAqlQuery/README.mdpp +++ b/Documentation/Books/Users/HttpAqlQuery/README.mdpp @@ -1,5 +1,7 @@ !CHAPTER HTTP Interface for AQL Queries +!SUBSECTION Explaining and parsing queries + ArangoDB has an Http interface to syntactically validate AQL queries. Furthermore, it offers an Http interface to retrieve the execution plan for any valid AQL query. @@ -12,4 +14,23 @@ inspect it and return meta information about it. @startDocuBlock JSF_post_api_explain -@startDocuBlock JSF_post_api_query \ No newline at end of file +@startDocuBlock JSF_post_api_query + + +!SUBSECTION Query tracking + +ArangoDB has an Http interface for retrieving the lists of currently +executing AQL queries and the list of slow AQL queries. In order to make meaningful +use of these APIs, query tracking needs to be enabled in the database the HTTP +request is executed for. + +@startDocuBlock GetApiQueryProperties + +@startDocuBlock PutApiQueryProperties + +@startDocuBlock GetApiQueryCurrent + +@startDocuBlock GetApiQuerySlow + +@startDocuBlock DeleteApiQuerySlow + diff --git a/arangod/Aql/QueryList.cpp b/arangod/Aql/QueryList.cpp index b539528edb..6396837259 100644 --- a/arangod/Aql/QueryList.cpp +++ b/arangod/Aql/QueryList.cpp @@ -175,6 +175,22 @@ void QueryList::remove (Query const* query, size_t length = entry->queryLength; if (length > maxLength) { length = maxLength; + // do not create invalid UTF-8 sequences + while (length > 0) { + uint8_t c = entry->queryString[length - 1]; + if ((c & 0b10000000) == 0) { + // single-byte character + break; + } + --length; + + // start of a multi-byte sequence + if ((c & 0b11000000) == 0b11000000) { + // decrease length by one more, so we the string contains the + // last part of the previous (multi-byte?) sequence + break; + } + } } _slow.emplace_back(QueryEntryCopy( @@ -227,6 +243,22 @@ std::vector QueryList::listCurrent () { size_t length = entry->queryLength; if (length > maxLength) { length = maxLength; + // do not create invalid UTF-8 sequences + while (length > 0) { + uint8_t c = entry->queryString[length - 1]; + if ((c & 0b10000000) == 0) { + // single-byte character + break; + } + --length; + + // start of a multi-byte sequence + if ((c & 0b11000000) == 0b11000000) { + // decrease length by one more, so we the string contains the + // last part of the previous (multi-byte?) sequence + break; + } + } } result.emplace_back(QueryEntryCopy( diff --git a/js/actions/api-query.js b/js/actions/api-query.js index d4426ab124..464a94d3fc 100644 --- a/js/actions/api-query.js +++ b/js/actions/api-query.js @@ -43,6 +43,18 @@ var ArangoError = arangodb.ArangoError; /// /// @RESTHEADER{GET /_api/query/current, Returns the currently running AQL queries} /// +/// Returns an array containing the AQL queries currently running in the selected +/// database. Each query is a JSON object with the following attributes: +/// +/// - *id*: the query's id +/// +/// - *query*: the query string (potentially truncated) +/// +/// - *started*: the date and time when the query was started +/// +/// - *runTime*: the query's run time up to the point the list of queries was +/// queried +/// /// @RESTRETURNCODES /// /// @RESTRETURNCODE{200} @@ -60,6 +72,24 @@ var ArangoError = arangodb.ArangoError; /// /// @RESTHEADER{GET /_api/query/slow, Returns the list of slow AQL queries} /// +/// Returns an array containing the last AQL queries that exceeded the slow +/// query threshold in the selected database. +/// The maximum amount of queries in the list can be controlled by setting +/// the query tracking property `maxSlowQueries`. The threshold for treating +/// a query as *slow* can be adjusted by setting the query tracking property +/// `slowQueryThreshold`. +/// +/// Each query is a JSON object with the following attributes: +/// +/// - *id*: the query's id +/// +/// - *query*: the query string (potentially truncated) +/// +/// - *started*: the date and time when the query was started +/// +/// - *runTime*: the query's run time up to the point the list of queries was +/// queried +/// /// @RESTRETURNCODES /// /// @RESTRETURNCODE{200} @@ -77,6 +107,31 @@ var ArangoError = arangodb.ArangoError; /// /// @RESTHEADER{GET /_api/query/properties, Returns the properties for the AQL query tracking} /// +/// Returns the current query tracking configuration. The configuration is a +/// JSON object with the following properties: +/// +/// - *enabled*: if set to *true*, then queries will be tracked. If set to +/// *false*, neither queries nor slow queries will be tracked. +/// +/// - *trackSlowQueries*: if set to *true*, then slow queries will be tracked +/// in the list of slow queries if their runtime exceeds the value set in +/// *slowQueryThreshold*. In order for slow queries to be tracked, the *enabled* +/// property must also be set to *true*. +/// +/// - *maxSlowQueries*: the maximum number of slow queries to keep in the list +/// of slow queries. If the list of slow queries is full, the oldest entry in +/// it will be discarded when additional slow queries occur. +/// +/// - *slowQueryThreshold*: the threshold value for treating a query as slow. A +/// query with a runtime greater or equal to this threshold value will be +/// put into the list of slow queries when slow query tracking is enabled. +/// The value for *slowQueryThreshold* is specified in seconds. +/// +/// - *maxQueryStringLength*: the maximum query string length to keep in the +/// list of queries. Query strings can have arbitrary lengths, and this property +/// can be used to save memory in case very long query strings are used. The +/// value is specified in bytes. +/// /// @RESTRETURNCODES /// /// @RESTRETURNCODE{200} @@ -151,10 +206,42 @@ function delete_api_query (req, res) { //////////////////////////////////////////////////////////////////////////////// /// @startDocuBlock PutApiQueryProperties -/// @brief chages the configuration for the AQL query tracking +/// @brief changes the configuration for the AQL query tracking /// /// @RESTHEADER{PUT /_api/query/properties, Changes the properties for the AQL query tracking} /// +/// @RESTBODYPARAM{properties,json,required} +/// The properties for query tracking in the current database. +/// +/// The properties need to be passed in the attribute *properties* in the body +/// of the HTTP request. *properties* needs to be a JSON object with the following +/// properties: +/// +/// - *enabled*: if set to *true*, then queries will be tracked. If set to +/// *false*, neither queries nor slow queries will be tracked. +/// +/// - *trackSlowQueries*: if set to *true*, then slow queries will be tracked +/// in the list of slow queries if their runtime exceeds the value set in +/// *slowQueryThreshold*. In order for slow queries to be tracked, the *enabled* +/// property must also be set to *true*. +/// +/// - *maxSlowQueries*: the maximum number of slow queries to keep in the list +/// of slow queries. If the list of slow queries is full, the oldest entry in +/// it will be discarded when additional slow queries occur. +/// +/// - *slowQueryThreshold*: the threshold value for treating a query as slow. A +/// query with a runtime greater or equal to this threshold value will be +/// put into the list of slow queries when slow query tracking is enabled. +/// The value for *slowQueryThreshold* is specified in seconds. +/// +/// - *maxQueryStringLength*: the maximum query string length to keep in the +/// list of queries. Query strings can have arbitrary lengths, and this property +/// can be used to save memory in case very long query strings are used. The +/// value is specified in bytes. +/// +/// After the properties have been changed, the current set of properties will +/// be returned in the HTTP response. +/// /// @RESTRETURNCODES /// /// @RESTRETURNCODE{200}