mirror of https://gitee.com/bigwinds/arangodb
3.5 -- intermediate commit stats (#9780)
* count intermediate commits add transactions statistics struct add tests put values in object / split test is multiple smaller tests * fix broken condition * fix test * remove print * fix windows build * fix mmfiles * fix cluster * add structs in docublocks * we do not know about intermediate commits on coordinators * add documentation * add isCluster function * add serverStatistics to 3.5 client * update documentation
This commit is contained in:
parent
6d53c1e02f
commit
44ab3f04b5
|
@ -1,6 +1,9 @@
|
||||||
v3.5.1 (XXXX-XX-XX)
|
v3.5.1 (XXXX-XX-XX)
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
|
* Add TransactionStatistics to ServerStatistics (transactions started /
|
||||||
|
aborted / committed and number of intermediate commits).
|
||||||
|
|
||||||
* Upgraded version of bundled curl library to 7.65.3.
|
* Upgraded version of bundled curl library to 7.65.3.
|
||||||
|
|
||||||
* Don't retry persisting follower information for collections/shards already
|
* Don't retry persisting follower information for collections/shards already
|
||||||
|
|
|
@ -16,6 +16,18 @@ In case of a distribution, the returned object contains the total count in
|
||||||
*count* and the distribution list in *counts*. The sum (or total) of the
|
*count* and the distribution list in *counts*. The sum (or total) of the
|
||||||
individual values is returned in *sum*.
|
individual values is returned in *sum*.
|
||||||
|
|
||||||
|
The transaction statistics show the local started, committed and aborted
|
||||||
|
transactions as well as intermediate commits done for the server queried. The
|
||||||
|
intermediate commit count will only take non zero values for the RocksDB
|
||||||
|
storage engine. Coordinators do almost no local transactions themselves in
|
||||||
|
their local databases, therefor cluster transactions (transactions started on a
|
||||||
|
coordinator that require DBServers to finish before the transactions is
|
||||||
|
committed cluster wide) are just added to their local statistics. This means
|
||||||
|
that the statistics you would see for a single server is roughly what you can
|
||||||
|
expect in a cluster setup using a single coordinator querying this coordinator.
|
||||||
|
Just with the difference that cluster transactions have no notion of
|
||||||
|
intermediate commits and will not increase the value.
|
||||||
|
|
||||||
@RESTRETURNCODES
|
@RESTRETURNCODES
|
||||||
|
|
||||||
@RESTRETURNCODE{200}
|
@RESTRETURNCODE{200}
|
||||||
|
@ -149,7 +161,20 @@ time the server is up and running
|
||||||
@RESTSTRUCT{physicalMemory,server_statistics_struct,integer,required,}
|
@RESTSTRUCT{physicalMemory,server_statistics_struct,integer,required,}
|
||||||
available physical memory on the server
|
available physical memory on the server
|
||||||
|
|
||||||
|
@RESTSTRUCT{transactions,server_statistics_struct,object,required,transactions_struct}
|
||||||
|
Statistics about transactions
|
||||||
|
|
||||||
|
@RESTSTRUCT{started,transactions_struct,integer,required,}
|
||||||
|
the number of started transactions
|
||||||
|
|
||||||
|
@RESTSTRUCT{committed,transactions_struct,integer,required,}
|
||||||
|
the number of committed transactions
|
||||||
|
|
||||||
|
@RESTSTRUCT{aborted,transactions_struct,integer,required,}
|
||||||
|
the number of aborted transactions
|
||||||
|
|
||||||
|
@RESTSTRUCT{intermediateCommits,transactions_struct,integer,required,}
|
||||||
|
the number of intermediate commits done
|
||||||
|
|
||||||
@RESTSTRUCT{v8Context,server_statistics_struct,object,required,v8_context_struct}
|
@RESTSTRUCT{v8Context,server_statistics_struct,object,required,v8_context_struct}
|
||||||
Statistics about the V8 javascript contexts
|
Statistics about the V8 javascript contexts
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include "Cluster/ClusterMethods.h"
|
#include "Cluster/ClusterMethods.h"
|
||||||
#include "Cluster/ClusterTrxMethods.h"
|
#include "Cluster/ClusterTrxMethods.h"
|
||||||
#include "ClusterEngine/ClusterEngine.h"
|
#include "ClusterEngine/ClusterEngine.h"
|
||||||
|
#include "Statistics/ServerStatistics.h"
|
||||||
#include "StorageEngine/EngineSelectorFeature.h"
|
#include "StorageEngine/EngineSelectorFeature.h"
|
||||||
#include "StorageEngine/TransactionCollection.h"
|
#include "StorageEngine/TransactionCollection.h"
|
||||||
#include "Transaction/Manager.h"
|
#include "Transaction/Manager.h"
|
||||||
|
@ -54,31 +55,33 @@ Result ClusterTransactionState::beginTransaction(transaction::Hints hints) {
|
||||||
// set hints
|
// set hints
|
||||||
_hints = hints;
|
_hints = hints;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto cleanup = scopeGuard([&] {
|
auto cleanup = scopeGuard([&] {
|
||||||
if (nestingLevel() == 0) {
|
if (nestingLevel() == 0) {
|
||||||
updateStatus(transaction::Status::ABORTED);
|
updateStatus(transaction::Status::ABORTED);
|
||||||
|
ServerStatistics::statistics()._transactionsStatistics._transactionsAborted++;
|
||||||
}
|
}
|
||||||
// free what we have got so far
|
// free what we have got so far
|
||||||
unuseCollections(nestingLevel());
|
unuseCollections(nestingLevel());
|
||||||
});
|
});
|
||||||
|
|
||||||
Result res = useCollections(nestingLevel());
|
Result res = useCollections(nestingLevel());
|
||||||
if (res.fail()) { // something is wrong
|
if (res.fail()) { // something is wrong
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
// all valid
|
// all valid
|
||||||
if (nestingLevel() == 0) {
|
if (nestingLevel() == 0) {
|
||||||
updateStatus(transaction::Status::RUNNING);
|
updateStatus(transaction::Status::RUNNING);
|
||||||
|
|
||||||
transaction::ManagerFeature::manager()->registerTransaction(id(), nullptr);
|
transaction::ManagerFeature::manager()->registerTransaction(id(), nullptr);
|
||||||
|
ServerStatistics::statistics()._transactionsStatistics._transactionsStarted++;
|
||||||
|
|
||||||
setRegistered();
|
setRegistered();
|
||||||
|
|
||||||
ClusterEngine* ce = static_cast<ClusterEngine*>(EngineSelectorFeature::ENGINE);
|
ClusterEngine* ce = static_cast<ClusterEngine*>(EngineSelectorFeature::ENGINE);
|
||||||
if (ce->isMMFiles() && hasHint(transaction::Hints::Hint::GLOBAL_MANAGED)) {
|
if (ce->isMMFiles() && hasHint(transaction::Hints::Hint::GLOBAL_MANAGED)) {
|
||||||
TRI_ASSERT(isCoordinator());
|
TRI_ASSERT(isCoordinator());
|
||||||
|
|
||||||
std::vector<std::string> leaders;
|
std::vector<std::string> leaders;
|
||||||
allCollections([&leaders](TransactionCollection& c) {
|
allCollections([&leaders](TransactionCollection& c) {
|
||||||
auto shardIds = c.collection()->shardIds();
|
auto shardIds = c.collection()->shardIds();
|
||||||
|
@ -90,7 +93,7 @@ Result ClusterTransactionState::beginTransaction(transaction::Hints hints) {
|
||||||
}
|
}
|
||||||
return true; // continue
|
return true; // continue
|
||||||
});
|
});
|
||||||
|
|
||||||
res = ClusterTrxMethods::beginTransactionOnLeaders(*this, leaders);
|
res = ClusterTrxMethods::beginTransactionOnLeaders(*this, leaders);
|
||||||
if (res.fail()) { // something is wrong
|
if (res.fail()) { // something is wrong
|
||||||
return res;
|
return res;
|
||||||
|
@ -99,7 +102,7 @@ Result ClusterTransactionState::beginTransaction(transaction::Hints hints) {
|
||||||
} else {
|
} else {
|
||||||
TRI_ASSERT(_status == transaction::Status::RUNNING);
|
TRI_ASSERT(_status == transaction::Status::RUNNING);
|
||||||
}
|
}
|
||||||
|
|
||||||
cleanup.cancel();
|
cleanup.cancel();
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
@ -117,6 +120,7 @@ Result ClusterTransactionState::commitTransaction(transaction::Methods* activeTr
|
||||||
arangodb::Result res;
|
arangodb::Result res;
|
||||||
if (nestingLevel() == 0) {
|
if (nestingLevel() == 0) {
|
||||||
updateStatus(transaction::Status::COMMITTED);
|
updateStatus(transaction::Status::COMMITTED);
|
||||||
|
ServerStatistics::statistics()._transactionsStatistics._transactionsCommitted++;
|
||||||
}
|
}
|
||||||
|
|
||||||
unuseCollections(nestingLevel());
|
unuseCollections(nestingLevel());
|
||||||
|
@ -130,6 +134,7 @@ Result ClusterTransactionState::abortTransaction(transaction::Methods* activeTrx
|
||||||
Result res;
|
Result res;
|
||||||
if (nestingLevel() == 0) {
|
if (nestingLevel() == 0) {
|
||||||
updateStatus(transaction::Status::ABORTED);
|
updateStatus(transaction::Status::ABORTED);
|
||||||
|
ServerStatistics::statistics()._transactionsStatistics._transactionsAborted++;
|
||||||
}
|
}
|
||||||
|
|
||||||
unuseCollections(nestingLevel());
|
unuseCollections(nestingLevel());
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
#include "StorageEngine/EngineSelectorFeature.h"
|
#include "StorageEngine/EngineSelectorFeature.h"
|
||||||
#include "StorageEngine/StorageEngine.h"
|
#include "StorageEngine/StorageEngine.h"
|
||||||
#include "StorageEngine/TransactionCollection.h"
|
#include "StorageEngine/TransactionCollection.h"
|
||||||
|
#include "Statistics/ServerStatistics.h"
|
||||||
#include "Transaction/Methods.h"
|
#include "Transaction/Methods.h"
|
||||||
#include "VocBase/LogicalCollection.h"
|
#include "VocBase/LogicalCollection.h"
|
||||||
#include "VocBase/ticks.h"
|
#include "VocBase/ticks.h"
|
||||||
|
@ -125,19 +126,21 @@ Result MMFilesTransactionState::beginTransaction(transaction::Hints hints) {
|
||||||
// all valid
|
// all valid
|
||||||
if (nestingLevel() == 0) {
|
if (nestingLevel() == 0) {
|
||||||
updateStatus(transaction::Status::RUNNING);
|
updateStatus(transaction::Status::RUNNING);
|
||||||
|
ServerStatistics::statistics()._transactionsStatistics._transactionsStarted++;
|
||||||
// defer writing of the begin marker until necessary!
|
// defer writing of the begin marker until necessary!
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// something is wrong
|
// something is wrong
|
||||||
if (nestingLevel() == 0) {
|
if (nestingLevel() == 0) {
|
||||||
updateStatus(transaction::Status::ABORTED);
|
updateStatus(transaction::Status::ABORTED);
|
||||||
|
ServerStatistics::statistics()._transactionsStatistics._transactionsAborted++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// free what we have got so far
|
// free what we have got so far
|
||||||
unuseCollections(nestingLevel());
|
unuseCollections(nestingLevel());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,6 +174,7 @@ Result MMFilesTransactionState::commitTransaction(transaction::Methods* activeTr
|
||||||
}
|
}
|
||||||
|
|
||||||
updateStatus(transaction::Status::COMMITTED);
|
updateStatus(transaction::Status::COMMITTED);
|
||||||
|
ServerStatistics::statistics()._transactionsStatistics._transactionsCommitted++;
|
||||||
|
|
||||||
// if a write query, clear the query cache for the participating collections
|
// if a write query, clear the query cache for the participating collections
|
||||||
if (AccessMode::isWriteOrExclusive(_type) && !_collections.empty() &&
|
if (AccessMode::isWriteOrExclusive(_type) && !_collections.empty() &&
|
||||||
|
@ -199,6 +203,7 @@ Result MMFilesTransactionState::abortTransaction(transaction::Methods* activeTrx
|
||||||
result.reset(res);
|
result.reset(res);
|
||||||
|
|
||||||
updateStatus(transaction::Status::ABORTED);
|
updateStatus(transaction::Status::ABORTED);
|
||||||
|
ServerStatistics::statistics()._transactionsStatistics._transactionsAborted++;
|
||||||
|
|
||||||
if (_hasOperations) {
|
if (_hasOperations) {
|
||||||
// must clean up the query cache because the transaction
|
// must clean up the query cache because the transaction
|
||||||
|
|
|
@ -39,6 +39,7 @@
|
||||||
#include "StorageEngine/EngineSelectorFeature.h"
|
#include "StorageEngine/EngineSelectorFeature.h"
|
||||||
#include "StorageEngine/StorageEngine.h"
|
#include "StorageEngine/StorageEngine.h"
|
||||||
#include "StorageEngine/TransactionCollection.h"
|
#include "StorageEngine/TransactionCollection.h"
|
||||||
|
#include "Statistics/ServerStatistics.h"
|
||||||
#include "Transaction/Context.h"
|
#include "Transaction/Context.h"
|
||||||
#include "Transaction/Manager.h"
|
#include "Transaction/Manager.h"
|
||||||
#include "Transaction/ManagerFeature.h"
|
#include "Transaction/ManagerFeature.h"
|
||||||
|
@ -102,6 +103,7 @@ Result RocksDBTransactionState::beginTransaction(transaction::Hints hints) {
|
||||||
// register with manager
|
// register with manager
|
||||||
transaction::ManagerFeature::manager()->registerTransaction(id(), nullptr);
|
transaction::ManagerFeature::manager()->registerTransaction(id(), nullptr);
|
||||||
updateStatus(transaction::Status::RUNNING);
|
updateStatus(transaction::Status::RUNNING);
|
||||||
|
ServerStatistics::statistics()._transactionsStatistics._transactionsStarted++;
|
||||||
|
|
||||||
setRegistered();
|
setRegistered();
|
||||||
|
|
||||||
|
@ -188,7 +190,7 @@ void RocksDBTransactionState::createTransaction() {
|
||||||
rocksdb::TransactionDB* db = rocksutils::globalRocksDB();
|
rocksdb::TransactionDB* db = rocksutils::globalRocksDB();
|
||||||
rocksdb::TransactionOptions trxOpts;
|
rocksdb::TransactionOptions trxOpts;
|
||||||
trxOpts.set_snapshot = true;
|
trxOpts.set_snapshot = true;
|
||||||
|
|
||||||
// unclear performance implications do not use for now
|
// unclear performance implications do not use for now
|
||||||
// trxOpts.deadlock_detect = !hasHint(transaction::Hints::Hint::NO_DLD);
|
// trxOpts.deadlock_detect = !hasHint(transaction::Hints::Hint::NO_DLD);
|
||||||
if (isOnlyExclusiveTransaction()) {
|
if (isOnlyExclusiveTransaction()) {
|
||||||
|
@ -336,7 +338,6 @@ arangodb::Result RocksDBTransactionState::internalCommit() {
|
||||||
coll->commitCounts(id(), postCommitSeq);
|
coll->commitCounts(id(), postCommitSeq);
|
||||||
committed = true;
|
committed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
// wait for sync if required, for all other platforms but Windows
|
// wait for sync if required, for all other platforms but Windows
|
||||||
if (waitForSync()) {
|
if (waitForSync()) {
|
||||||
|
@ -391,6 +392,7 @@ Result RocksDBTransactionState::commitTransaction(transaction::Methods* activeTr
|
||||||
if (res.ok()) {
|
if (res.ok()) {
|
||||||
updateStatus(transaction::Status::COMMITTED);
|
updateStatus(transaction::Status::COMMITTED);
|
||||||
cleanupTransaction(); // deletes trx
|
cleanupTransaction(); // deletes trx
|
||||||
|
ServerStatistics::statistics()._transactionsStatistics._transactionsCommitted++;
|
||||||
} else {
|
} else {
|
||||||
abortTransaction(activeTrx); // deletes trx
|
abortTransaction(activeTrx); // deletes trx
|
||||||
}
|
}
|
||||||
|
@ -422,6 +424,7 @@ Result RocksDBTransactionState::abortTransaction(transaction::Methods* activeTrx
|
||||||
TRI_ASSERT(!_rocksTransaction && !_cacheTx && !_readSnapshot);
|
TRI_ASSERT(!_rocksTransaction && !_cacheTx && !_readSnapshot);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ServerStatistics::statistics()._transactionsStatistics._transactionsAborted++;
|
||||||
unuseCollections(nestingLevel());
|
unuseCollections(nestingLevel());
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -593,6 +596,7 @@ Result RocksDBTransactionState::triggerIntermediateCommit(bool& hasPerformedInte
|
||||||
}
|
}
|
||||||
|
|
||||||
hasPerformedIntermediateCommit = true;
|
hasPerformedIntermediateCommit = true;
|
||||||
|
ServerStatistics::statistics()._transactionsStatistics._intermediateCommits++;
|
||||||
|
|
||||||
TRI_IF_FAILURE("FailAfterIntermediateCommit") {
|
TRI_IF_FAILURE("FailAfterIntermediateCommit") {
|
||||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_DEBUG);
|
THROW_ARANGO_EXCEPTION(TRI_ERROR_DEBUG);
|
||||||
|
|
|
@ -351,10 +351,17 @@ stats::Descriptions::Descriptions()
|
||||||
}
|
}
|
||||||
|
|
||||||
void stats::Descriptions::serverStatistics(velocypack::Builder& b) const {
|
void stats::Descriptions::serverStatistics(velocypack::Builder& b) const {
|
||||||
ServerStatistics info = ServerStatistics::statistics();
|
ServerStatistics const& info = ServerStatistics::statistics();
|
||||||
b.add("uptime", VPackValue(info._uptime));
|
b.add("uptime", VPackValue(info._uptime));
|
||||||
b.add("physicalMemory", VPackValue(TRI_PhysicalMemory));
|
b.add("physicalMemory", VPackValue(TRI_PhysicalMemory));
|
||||||
|
|
||||||
|
b.add("transactions", VPackValue(VPackValueType::Object));
|
||||||
|
b.add("started", VPackValue(info._transactionsStatistics._transactionsStarted));
|
||||||
|
b.add("aborted", VPackValue(info._transactionsStatistics._transactionsAborted));
|
||||||
|
b.add("committed", VPackValue(info._transactionsStatistics._transactionsCommitted));
|
||||||
|
b.add("intermediateCommits", VPackValue(info._transactionsStatistics._intermediateCommits));
|
||||||
|
b.close();
|
||||||
|
|
||||||
V8DealerFeature* dealer =
|
V8DealerFeature* dealer =
|
||||||
application_features::ApplicationServer::getFeature<V8DealerFeature>(
|
application_features::ApplicationServer::getFeature<V8DealerFeature>(
|
||||||
"V8Dealer");
|
"V8Dealer");
|
||||||
|
|
|
@ -30,19 +30,18 @@ using namespace arangodb;
|
||||||
// --SECTION-- static members
|
// --SECTION-- static members
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
double ServerStatistics::START_TIME = 0.0;
|
ServerStatistics serverStatisticsGlobal(0);
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// --SECTION-- static public methods
|
// --SECTION-- static public methods
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
ServerStatistics ServerStatistics::statistics() {
|
ServerStatistics& ServerStatistics::statistics() {
|
||||||
ServerStatistics server;
|
//update the uptime for everyone reading the statistics.
|
||||||
|
serverStatisticsGlobal._uptime = StatisticsFeature::time() - serverStatisticsGlobal._startTime;
|
||||||
server._startTime = START_TIME;
|
return serverStatisticsGlobal;
|
||||||
server._uptime = StatisticsFeature::time() - START_TIME;
|
|
||||||
|
|
||||||
return server;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServerStatistics::initialize() { START_TIME = StatisticsFeature::time(); }
|
void ServerStatistics::initialize(double startTime) {
|
||||||
|
serverStatisticsGlobal._startTime = startTime;
|
||||||
|
}
|
||||||
|
|
|
@ -24,18 +24,35 @@
|
||||||
#ifndef ARANGOD_STATISTICS_SERVER_STATISTICS_H
|
#ifndef ARANGOD_STATISTICS_SERVER_STATISTICS_H
|
||||||
#define ARANGOD_STATISTICS_SERVER_STATISTICS_H 1
|
#define ARANGOD_STATISTICS_SERVER_STATISTICS_H 1
|
||||||
|
|
||||||
class ServerStatistics {
|
#include <atomic>
|
||||||
public:
|
#include <memory>
|
||||||
static ServerStatistics statistics();
|
|
||||||
|
|
||||||
static void initialize();
|
|
||||||
|
|
||||||
|
struct TransactionStatistics {
|
||||||
|
TransactionStatistics() : _transactionsStarted(0), _transactionsAborted(0)
|
||||||
|
, _transactionsCommitted(0), _intermediateCommits(0) {};
|
||||||
|
|
||||||
|
std::atomic<std::uint64_t> _transactionsStarted;
|
||||||
|
std::atomic<std::uint64_t> _transactionsAborted;
|
||||||
|
std::atomic<std::uint64_t> _transactionsCommitted;
|
||||||
|
std::atomic<std::uint64_t> _intermediateCommits;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ServerStatistics {
|
||||||
|
|
||||||
|
ServerStatistics(ServerStatistics const&) = delete;
|
||||||
|
ServerStatistics(ServerStatistics &&) = delete;
|
||||||
|
ServerStatistics& operator=(ServerStatistics const&) = delete;
|
||||||
|
ServerStatistics& operator=(ServerStatistics &&) = delete;
|
||||||
|
|
||||||
|
static ServerStatistics& statistics();
|
||||||
|
static void initialize(double);
|
||||||
|
|
||||||
|
TransactionStatistics _transactionsStatistics;
|
||||||
double _startTime;
|
double _startTime;
|
||||||
double _uptime;
|
std::atomic<double> _uptime;
|
||||||
|
|
||||||
private:
|
ServerStatistics(double start) : _transactionsStatistics(), _startTime(start), _uptime(0.0) {}
|
||||||
static double START_TIME;
|
|
||||||
ServerStatistics() : _startTime(0.0), _uptime(0.0) {}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -155,7 +155,7 @@ void StatisticsFeature::prepare() {
|
||||||
|
|
||||||
STATISTICS = this;
|
STATISTICS = this;
|
||||||
|
|
||||||
ServerStatistics::initialize();
|
ServerStatistics::initialize(StatisticsFeature::time());
|
||||||
ConnectionStatistics::initialize();
|
ConnectionStatistics::initialize();
|
||||||
RequestStatistics::initialize();
|
RequestStatistics::initialize();
|
||||||
}
|
}
|
||||||
|
|
|
@ -840,7 +840,7 @@ void StatisticsWorker::generateRawStatistics(VPackBuilder& builder, double const
|
||||||
|
|
||||||
RequestStatistics::fill(totalTime, requestTime, queueTime, ioTime, bytesSent, bytesReceived);
|
RequestStatistics::fill(totalTime, requestTime, queueTime, ioTime, bytesSent, bytesReceived);
|
||||||
|
|
||||||
ServerStatistics serverInfo = ServerStatistics::statistics();
|
ServerStatistics const& serverInfo = ServerStatistics::statistics();
|
||||||
|
|
||||||
V8DealerFeature* dealer =
|
V8DealerFeature* dealer =
|
||||||
application_features::ApplicationServer::getFeature<V8DealerFeature>(
|
application_features::ApplicationServer::getFeature<V8DealerFeature>(
|
||||||
|
@ -922,6 +922,12 @@ void StatisticsWorker::generateRawStatistics(VPackBuilder& builder, double const
|
||||||
builder.add("server", VPackValue(VPackValueType::Object));
|
builder.add("server", VPackValue(VPackValueType::Object));
|
||||||
builder.add("uptime", VPackValue(serverInfo._uptime));
|
builder.add("uptime", VPackValue(serverInfo._uptime));
|
||||||
builder.add("physicalMemory", VPackValue(TRI_PhysicalMemory));
|
builder.add("physicalMemory", VPackValue(TRI_PhysicalMemory));
|
||||||
|
builder.add("transactions", VPackValue(VPackValueType::Object));
|
||||||
|
builder.add("started", VPackValue(serverInfo._transactionsStatistics._transactionsStarted));
|
||||||
|
builder.add("aborted", VPackValue(serverInfo._transactionsStatistics._transactionsAborted));
|
||||||
|
builder.add("committed", VPackValue(serverInfo._transactionsStatistics._transactionsCommitted));
|
||||||
|
builder.add("intermediateCommits", VPackValue(serverInfo._transactionsStatistics._intermediateCommits));
|
||||||
|
builder.close();
|
||||||
|
|
||||||
// export v8 statistics
|
// export v8 statistics
|
||||||
builder.add("v8Context", VPackValue(VPackValueType::Object));
|
builder.add("v8Context", VPackValue(VPackValueType::Object));
|
||||||
|
@ -958,7 +964,7 @@ void StatisticsWorker::generateRawStatistics(VPackBuilder& builder, double const
|
||||||
builder.add("threads", VPackValue(VPackValueType::Object));
|
builder.add("threads", VPackValue(VPackValueType::Object));
|
||||||
SchedulerFeature::SCHEDULER->toVelocyPack(builder);
|
SchedulerFeature::SCHEDULER->toVelocyPack(builder);
|
||||||
builder.close();
|
builder.close();
|
||||||
|
|
||||||
// export ttl statistics
|
// export ttl statistics
|
||||||
TtlFeature* ttlFeature =
|
TtlFeature* ttlFeature =
|
||||||
application_features::ApplicationServer::getFeature<TtlFeature>("Ttl");
|
application_features::ApplicationServer::getFeature<TtlFeature>("Ttl");
|
||||||
|
|
|
@ -98,7 +98,7 @@ static void JS_ServerStatistics(v8::FunctionCallbackInfo<v8::Value> const& args)
|
||||||
TRI_V8_TRY_CATCH_BEGIN(isolate)
|
TRI_V8_TRY_CATCH_BEGIN(isolate)
|
||||||
v8::HandleScope scope(isolate);
|
v8::HandleScope scope(isolate);
|
||||||
|
|
||||||
ServerStatistics info = ServerStatistics::statistics();
|
ServerStatistics const& info = ServerStatistics::statistics();
|
||||||
|
|
||||||
v8::Handle<v8::Object> result = v8::Object::New(isolate);
|
v8::Handle<v8::Object> result = v8::Object::New(isolate);
|
||||||
|
|
||||||
|
@ -107,12 +107,25 @@ static void JS_ServerStatistics(v8::FunctionCallbackInfo<v8::Value> const& args)
|
||||||
result->Set(TRI_V8_ASCII_STRING(isolate, "physicalMemory"),
|
result->Set(TRI_V8_ASCII_STRING(isolate, "physicalMemory"),
|
||||||
v8::Number::New(isolate, (double)TRI_PhysicalMemory));
|
v8::Number::New(isolate, (double)TRI_PhysicalMemory));
|
||||||
|
|
||||||
v8::Handle<v8::Object> v8CountersObj = v8::Object::New(isolate);
|
// transaction info
|
||||||
|
auto const& ts = info._transactionsStatistics;
|
||||||
|
v8::Handle<v8::Object> v8TransactionInfoObj = v8::Object::New(isolate);
|
||||||
|
v8TransactionInfoObj->Set(TRI_V8_ASCII_STRING(isolate, "started"),
|
||||||
|
v8::Number::New(isolate, (double)ts._transactionsStarted));
|
||||||
|
v8TransactionInfoObj->Set(TRI_V8_ASCII_STRING(isolate, "aborted"),
|
||||||
|
v8::Number::New(isolate, (double)ts._transactionsAborted));
|
||||||
|
v8TransactionInfoObj->Set(TRI_V8_ASCII_STRING(isolate, "committed"),
|
||||||
|
v8::Number::New(isolate, (double)ts._transactionsCommitted));
|
||||||
|
v8TransactionInfoObj->Set(TRI_V8_ASCII_STRING(isolate, "intermediateCommits"),
|
||||||
|
v8::Number::New(isolate, (double)ts._intermediateCommits));
|
||||||
|
result->Set(TRI_V8_ASCII_STRING(isolate, "transactions"), v8TransactionInfoObj);
|
||||||
|
|
||||||
|
// v8 counters
|
||||||
V8DealerFeature* dealer =
|
V8DealerFeature* dealer =
|
||||||
application_features::ApplicationServer::getFeature<V8DealerFeature>(
|
application_features::ApplicationServer::getFeature<V8DealerFeature>(
|
||||||
"V8Dealer");
|
"V8Dealer");
|
||||||
|
|
||||||
auto v8Counters = dealer->getCurrentContextNumbers();
|
auto v8Counters = dealer->getCurrentContextNumbers();
|
||||||
|
v8::Handle<v8::Object> v8CountersObj = v8::Object::New(isolate);
|
||||||
v8CountersObj->Set(TRI_V8_ASCII_STRING(isolate, "available"),
|
v8CountersObj->Set(TRI_V8_ASCII_STRING(isolate, "available"),
|
||||||
v8::Number::New(isolate, static_cast<int32_t>(v8Counters.available)));
|
v8::Number::New(isolate, static_cast<int32_t>(v8Counters.available)));
|
||||||
v8CountersObj->Set(TRI_V8_ASCII_STRING(isolate, "busy"),
|
v8CountersObj->Set(TRI_V8_ASCII_STRING(isolate, "busy"),
|
||||||
|
@ -146,7 +159,7 @@ static void JS_ServerStatistics(v8::FunctionCallbackInfo<v8::Value> const& args)
|
||||||
|
|
||||||
v8CountersObj->Set(TRI_V8_ASCII_STRING(isolate, "memory"),
|
v8CountersObj->Set(TRI_V8_ASCII_STRING(isolate, "memory"),
|
||||||
v8ListOfMemory);
|
v8ListOfMemory);
|
||||||
|
|
||||||
result->Set(TRI_V8_ASCII_STRING(isolate, "v8Context"), v8CountersObj);
|
result->Set(TRI_V8_ASCII_STRING(isolate, "v8Context"), v8CountersObj);
|
||||||
|
|
||||||
v8::Handle<v8::Object> counters = v8::Object::New(isolate);
|
v8::Handle<v8::Object> counters = v8::Object::New(isolate);
|
||||||
|
|
|
@ -334,6 +334,22 @@
|
||||||
exports.output(level, ': ', msg, '\n');
|
exports.output(level, ': ', msg, '\n');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
exports.isCluster = function () {
|
||||||
|
const arangosh = require('@arangodb/arangosh');
|
||||||
|
let requestResult = exports.arango.GET("/_admin/server/role");
|
||||||
|
arangosh.checkRequestResult(requestResult);
|
||||||
|
return requestResult.role === "COORDINATOR";
|
||||||
|
};
|
||||||
|
|
||||||
|
// / @brief serverStatistics
|
||||||
|
exports.serverStatistics = function () {
|
||||||
|
const arangosh = require('@arangodb/arangosh');
|
||||||
|
let requestResult = exports.arango.GET('/_admin/statistics');
|
||||||
|
arangosh.checkRequestResult(requestResult);
|
||||||
|
return requestResult.server;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
// //////////////////////////////////////////////////////////////////////////////
|
// //////////////////////////////////////////////////////////////////////////////
|
||||||
// / @brief sprintf wrapper
|
// / @brief sprintf wrapper
|
||||||
// //////////////////////////////////////////////////////////////////////////////
|
// //////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -526,5 +526,14 @@
|
||||||
exports.debugCanUseFailAt = global.SYS_DEBUG_CAN_USE_FAILAT;
|
exports.debugCanUseFailAt = global.SYS_DEBUG_CAN_USE_FAILAT;
|
||||||
delete global.SYS_DEBUG_CAN_USE_FAILAT;
|
delete global.SYS_DEBUG_CAN_USE_FAILAT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// /////////////////////////////////////////////////////////////////////////////
|
||||||
|
// / @brief whether or not clustering is enabled
|
||||||
|
// /////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
exports.isCluster = function () {
|
||||||
|
var role = global.ArangoServerState.role();
|
||||||
|
return (role !== undefined && role !== 'SINGLE' && role !== 'AGENT');
|
||||||
|
};
|
||||||
|
|
||||||
}());
|
}());
|
||||||
|
|
|
@ -26,6 +26,8 @@
|
||||||
// / @author Simon Grätzer
|
// / @author Simon Grätzer
|
||||||
// //////////////////////////////////////////////////////////////////////////////
|
// //////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// tests for streaming transactions
|
||||||
|
|
||||||
var jsunity = require('jsunity');
|
var jsunity = require('jsunity');
|
||||||
var internal = require('internal');
|
var internal = require('internal');
|
||||||
var arangodb = require('@arangodb');
|
var arangodb = require('@arangodb');
|
||||||
|
|
|
@ -0,0 +1,133 @@
|
||||||
|
/*jshint globalstrict:false, strict:false */
|
||||||
|
/*global assertEqual, assertTrue, assertMatch, fail */
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief tests for client/server side transaction invocation
|
||||||
|
///
|
||||||
|
/// @file
|
||||||
|
///
|
||||||
|
/// DISCLAIMER
|
||||||
|
///
|
||||||
|
/// Copyright 2019 ArangoDB Inc, 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 Jan Christoph Uhde
|
||||||
|
/// @author Copyright 2019, ArangodDB Inc, Cologne, Germany
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
const jsunity = require("jsunity");
|
||||||
|
const internal = require("internal");
|
||||||
|
const db = require("@arangodb").db;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief test suite
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
function CommonStatisticsSuite() {
|
||||||
|
'use strict';
|
||||||
|
let c;
|
||||||
|
return {
|
||||||
|
setUp: function () {
|
||||||
|
c = db._create("shellCommonStatTestCollection");
|
||||||
|
},
|
||||||
|
tearDown: function () {
|
||||||
|
db._drop("shellCommonStatTestCollection");
|
||||||
|
},
|
||||||
|
|
||||||
|
testServerStatsStructure: function () {
|
||||||
|
let stats = internal.serverStatistics();
|
||||||
|
assertTrue(Number.isInteger(stats.transactions.started));
|
||||||
|
assertTrue(Number.isInteger(stats.transactions.committed));
|
||||||
|
assertTrue(Number.isInteger(stats.transactions.aborted));
|
||||||
|
assertTrue(Number.isInteger(stats.transactions.intermediateCommits));
|
||||||
|
},
|
||||||
|
|
||||||
|
testServerStatsCommit: function () {
|
||||||
|
let stats1 = internal.serverStatistics();
|
||||||
|
c.insert({ "gondel" : "ulf" });
|
||||||
|
let stats2 = internal.serverStatistics();
|
||||||
|
|
||||||
|
assertTrue(stats1.transactions.started < stats2.transactions.started
|
||||||
|
, "1 started: " + stats1.transactions.started
|
||||||
|
+ " -- 2 started: " + stats2.transactions.started);
|
||||||
|
assertTrue(stats1.transactions.committed < stats2.transactions.committed);
|
||||||
|
},
|
||||||
|
|
||||||
|
testServerStatsAbort: function () {
|
||||||
|
let stats1 = internal.serverStatistics();
|
||||||
|
let stats2;
|
||||||
|
try {
|
||||||
|
db._executeTransaction({
|
||||||
|
collections: {},
|
||||||
|
action: function () {
|
||||||
|
var err = new Error('abort on purpose');
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
fail();
|
||||||
|
} catch (err) {
|
||||||
|
stats2 = internal.serverStatistics();
|
||||||
|
assertMatch(/abort on purpose/, err.errorMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
assertTrue(stats1.transactions.started < stats2.transactions.started);
|
||||||
|
assertTrue(stats1.transactions.aborted < stats2.transactions.aborted);
|
||||||
|
},
|
||||||
|
|
||||||
|
testIntermediateCommitsCommit: function () {
|
||||||
|
let stats1 = internal.serverStatistics();
|
||||||
|
db._query(`FOR i IN 1..3 INSERT { "ulf" : i } IN ${c.name()}`, {}, { "intermediateCommitCount" : 2});
|
||||||
|
let stats2 = internal.serverStatistics();
|
||||||
|
|
||||||
|
if(db._engine().name === "rocksdb" && !internal.isCluster()) {
|
||||||
|
assertTrue(stats1.transactions.intermediateCommits < stats2.transactions.intermediateCommits);
|
||||||
|
} else {
|
||||||
|
assertEqual(stats1.transactions.intermediateCommits, 0);
|
||||||
|
}
|
||||||
|
assertTrue(stats1.transactions.committed < stats2.transactions.committed);
|
||||||
|
},
|
||||||
|
|
||||||
|
testIntermediateCommitsAbort: function () {
|
||||||
|
let stats1 = internal.serverStatistics();
|
||||||
|
let stats2;
|
||||||
|
try {
|
||||||
|
let rv = db._query(`FOR i IN 1..3
|
||||||
|
FILTER ASSERT(i == 0, "abort on purpose")
|
||||||
|
INSERT { "ulf" : i } IN ${c.name()}
|
||||||
|
`, {}, { "intermediateCommitCount" : 2});
|
||||||
|
fail();
|
||||||
|
} catch (err) {
|
||||||
|
stats2 = internal.serverStatistics();
|
||||||
|
assertMatch(/abort on purpose/, err.errorMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(db._engine().name === "rocksdb" && !internal.isCluster()) {
|
||||||
|
assertTrue(stats1.transactions.intermediateCommits <= stats2.transactions.intermediateCommits);
|
||||||
|
} else {
|
||||||
|
assertEqual(stats1.transactions.intermediateCommits, 0);
|
||||||
|
}
|
||||||
|
assertTrue(stats1.transactions.aborted < stats2.transactions.aborted);
|
||||||
|
},
|
||||||
|
}; //return
|
||||||
|
} // CommonStatisticsSuite end
|
||||||
|
|
||||||
|
|
||||||
|
jsunity.run(CommonStatisticsSuite);
|
||||||
|
|
||||||
|
return jsunity.done();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue