1
0
Fork 0

Improved RocksDB engine statistics with docs and rest endpoint (#2598)

* Improved statistics reporting for RocksDB engine (including cache info).

* Added documentation about db._engineStats().

* Added rest endpoint for engine stats.
This commit is contained in:
Dan Larkin 2017-06-18 16:55:25 -04:00 committed by Frank Celler
parent 9b53d3cd45
commit a0c4e3d9df
6 changed files with 120 additions and 32 deletions

View File

@ -184,3 +184,12 @@ database. The *_system* database itself cannot be dropped.
Databases are dropped asynchronously, and will be physically removed if Databases are dropped asynchronously, and will be physically removed if
all clients have disconnected and references have been garbage-collected. all clients have disconnected and references have been garbage-collected.
### Engine statistics
retrieve statistics related to the storage engine-rocksdb
`db._engineStats()`
Returns some statistics related to storage engine activity, including figures
about data size, cache usage, etc.
**Note**: Currently this only produces useful output for the RocksDB engine.

View File

@ -257,7 +257,7 @@ std::pair<double, double> Manager::globalHitRates() {
uint64_t currentHits = _findHits.load(); uint64_t currentHits = _findHits.load();
uint64_t currentMisses = _findMisses.load(); uint64_t currentMisses = _findMisses.load();
if (currentHits + currentMisses > 0) { if (currentHits + currentMisses > 0) {
lifetimeRate = 100 * (static_cast<double>(currentHits) / lifetimeRate = 100.0 * (static_cast<double>(currentHits) /
static_cast<double>(currentHits + currentMisses)); static_cast<double>(currentHits + currentMisses));
} }
@ -278,7 +278,8 @@ std::pair<double, double> Manager::globalHitRates() {
currentMisses = (*stats)[0].second; currentMisses = (*stats)[0].second;
} }
if (currentHits + currentMisses > 0) { if (currentHits + currentMisses > 0) {
windowedRate = 100 * (static_cast<double>(currentHits) / windowedRate =
100.0 * (static_cast<double>(currentHits) /
static_cast<double>(currentHits + currentMisses)); static_cast<double>(currentHits + currentMisses));
} }
} }
@ -750,8 +751,8 @@ std::shared_ptr<Manager::PriorityList> Manager::priorityList() {
double baseWeight = std::max(minimumWeight, uniformMarginalWeight); double baseWeight = std::max(minimumWeight, uniformMarginalWeight);
#ifdef ARANGODB_ENABLE_MAINTAINER_MODE #ifdef ARANGODB_ENABLE_MAINTAINER_MODE
if (1.0 < (baseWeight * static_cast<double>(_caches.size()))) { if (1.0 < (baseWeight * static_cast<double>(_caches.size()))) {
LOG_TOPIC(FATAL, Logger::FIXME) << "weight: " << baseWeight LOG_TOPIC(FATAL, Logger::FIXME)
<< ", count: " << _caches.size(); << "weight: " << baseWeight << ", count: " << _caches.size();
TRI_ASSERT(1.0 >= (baseWeight * static_cast<double>(_caches.size()))); TRI_ASSERT(1.0 >= (baseWeight * static_cast<double>(_caches.size())));
} }
#endif #endif

View File

@ -443,11 +443,11 @@ void GeneralServerFeature::defineHandlers() {
AsyncJobManager*>, AsyncJobManager*>,
_jobManager.get()); _jobManager.get());
_handlerFactory->addHandler( _handlerFactory->addPrefixHandler(
"/_api/version", RestHandlerCreator<RestVersionHandler>::createNoData); "/_api/engine", RestHandlerCreator<RestEngineHandler>::createNoData);
_handlerFactory->addHandler( _handlerFactory->addHandler(
"/_api/engine", RestHandlerCreator<RestEngineHandler>::createNoData); "/_api/version", RestHandlerCreator<RestVersionHandler>::createNoData);
#ifdef ARANGODB_ENABLE_MAINTAINER_MODE #ifdef ARANGODB_ENABLE_MAINTAINER_MODE
_handlerFactory->addHandler( _handlerFactory->addHandler(

View File

@ -38,10 +38,51 @@ RestEngineHandler::RestEngineHandler(GeneralRequest* request,
: RestBaseHandler(request, response) {} : RestBaseHandler(request, response) {}
RestStatus RestEngineHandler::execute() { RestStatus RestEngineHandler::execute() {
// extract the sub-request type
auto const type = _request->requestType();
if (type == rest::RequestType::GET) {
handleGet();
return RestStatus::DONE;
}
generateError(rest::ResponseCode::METHOD_NOT_ALLOWED,
TRI_ERROR_HTTP_METHOD_NOT_ALLOWED);
return RestStatus::DONE;
}
void RestEngineHandler::handleGet() {
std::vector<std::string> const& suffixes = _request->suffixes();
if (suffixes.size() > 1 || (suffixes.size() == 1 && suffixes[0] != "stats")) {
generateError(rest::ResponseCode::BAD, TRI_ERROR_BAD_PARAMETER,
"expecting GET /_api/engine[/stats]");
return;
}
if (suffixes.size() == 0) {
getCapabilities();
return;
}
getStats();
return;
}
void RestEngineHandler::getCapabilities() {
VPackBuilder result; VPackBuilder result;
StorageEngine* engine = EngineSelectorFeature::ENGINE; StorageEngine* engine = EngineSelectorFeature::ENGINE;
engine->getCapabilities(result); engine->getCapabilities(result);
generateResult(rest::ResponseCode::OK, result.slice()); generateResult(rest::ResponseCode::OK, result.slice());
return RestStatus::DONE; return;
}
void RestEngineHandler::getStats() {
VPackBuilder result;
StorageEngine* engine = EngineSelectorFeature::ENGINE;
engine->getStatistics(result);
generateResult(rest::ResponseCode::OK, result.slice());
return;
} }

View File

@ -35,6 +35,11 @@ class RestEngineHandler : public arangodb::RestBaseHandler {
char const* name() const override final { return "RestEngineHandler"; } char const* name() const override final { return "RestEngineHandler"; }
bool isDirect() const override { return true; } bool isDirect() const override { return true; }
RestStatus execute() override; RestStatus execute() override;
protected:
void handleGet();
void getCapabilities();
void getStats();
}; };
} }

View File

@ -34,6 +34,8 @@
#include "Basics/VelocyPackHelper.h" #include "Basics/VelocyPackHelper.h"
#include "Basics/WriteLocker.h" #include "Basics/WriteLocker.h"
#include "Basics/build.h" #include "Basics/build.h"
#include "Cache/CacheManagerFeature.h"
#include "Cache/Manager.h"
#include "GeneralServer/RestHandlerFactory.h" #include "GeneralServer/RestHandlerFactory.h"
#include "Logger/Logger.h" #include "Logger/Logger.h"
#include "ProgramOptions/ProgramOptions.h" #include "ProgramOptions/ProgramOptions.h"
@ -1414,29 +1416,52 @@ RocksDBReplicationManager* RocksDBEngine::replicationManager() const {
void RocksDBEngine::getStatistics(VPackBuilder& builder) const { void RocksDBEngine::getStatistics(VPackBuilder& builder) const {
builder.openObject(); builder.openObject();
// add int properties // add int properties
auto c1 = [&](std::string const& s) { auto addInt = [&](std::string const& s) {
std::string v;
if (_db->GetProperty(s, &v)) {
int64_t i = basics::StringUtils::int64(v);
builder.add(s, VPackValue(i));
}
};
auto addStr = [&](std::string const& s) {
std::string v; std::string v;
if (_db->GetProperty(s, &v)) { if (_db->GetProperty(s, &v)) {
builder.add(s, VPackValue(v)); builder.add(s, VPackValue(v));
} }
}; };
c1(rocksdb::DB::Properties::kNumImmutableMemTable); auto addCf = [&](std::string const& name, rocksdb::ColumnFamilyHandle* c) {
c1(rocksdb::DB::Properties::kMemTableFlushPending); std::string v;
c1(rocksdb::DB::Properties::kCompactionPending); if (_db->GetProperty(c, rocksdb::DB::Properties::kCFStats, &v)) {
c1(rocksdb::DB::Properties::kBackgroundErrors); builder.add(name, VPackValue(v));
c1(rocksdb::DB::Properties::kCurSizeActiveMemTable); }
c1(rocksdb::DB::Properties::kCurSizeAllMemTables); };
c1(rocksdb::DB::Properties::kSizeAllMemTables); addInt(rocksdb::DB::Properties::kNumImmutableMemTable);
c1(rocksdb::DB::Properties::kNumEntriesImmMemTables); addInt(rocksdb::DB::Properties::kMemTableFlushPending);
c1(rocksdb::DB::Properties::kNumSnapshots); addInt(rocksdb::DB::Properties::kCompactionPending);
c1(rocksdb::DB::Properties::kDBStats); addInt(rocksdb::DB::Properties::kBackgroundErrors);
c1(rocksdb::DB::Properties::kCFStats); addInt(rocksdb::DB::Properties::kCurSizeActiveMemTable);
c1(rocksdb::DB::Properties::kSSTables); addInt(rocksdb::DB::Properties::kCurSizeAllMemTables);
c1(rocksdb::DB::Properties::kNumRunningCompactions); addInt(rocksdb::DB::Properties::kSizeAllMemTables);
c1(rocksdb::DB::Properties::kNumRunningFlushes); addInt(rocksdb::DB::Properties::kNumEntriesImmMemTables);
c1(rocksdb::DB::Properties::kIsFileDeletionsEnabled); addInt(rocksdb::DB::Properties::kNumSnapshots);
c1(rocksdb::DB::Properties::kBaseLevel); addStr(rocksdb::DB::Properties::kDBStats);
c1(rocksdb::DB::Properties::kTotalSstFilesSize); addStr(rocksdb::DB::Properties::kSSTables);
addInt(rocksdb::DB::Properties::kNumRunningCompactions);
addInt(rocksdb::DB::Properties::kNumRunningFlushes);
addInt(rocksdb::DB::Properties::kIsFileDeletionsEnabled);
addInt(rocksdb::DB::Properties::kBaseLevel);
addInt(rocksdb::DB::Properties::kTotalSstFilesSize);
builder.add("rocksdb.cfstats", VPackValue(VPackValueType::Object));
addCf("other", RocksDBColumnFamily::other());
addCf("documents", RocksDBColumnFamily::documents());
addCf("primary", RocksDBColumnFamily::primary());
addCf("edge", RocksDBColumnFamily::edge());
addCf("geo", RocksDBColumnFamily::geo());
addCf("fulltext", RocksDBColumnFamily::fulltext());
addCf("index", RocksDBColumnFamily::index());
addCf("uniqueIndex", RocksDBColumnFamily::uniqueIndex());
addCf("views", RocksDBColumnFamily::views());
builder.close();
if (_options.table_factory) { if (_options.table_factory) {
void* options = _options.table_factory->GetOptions(); void* options = _options.table_factory->GetOptions();
@ -1445,6 +1470,13 @@ void RocksDBEngine::getStatistics(VPackBuilder& builder) const {
} }
} }
cache::Manager* manager = CacheManagerFeature::MANAGER;
auto rates = manager->globalHitRates();
builder.add("cache.size", VPackValue(manager->globalLimit()));
builder.add("cache.used", VPackValue(manager->globalAllocation()));
builder.add("cache.hit-rate-lifetime", VPackValue(rates.first));
builder.add("cache.hit-rate-recent", VPackValue(rates.second));
builder.close(); builder.close();
} }