mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
Performance logging and counters:
* Tally and duration counters for Job Queue tasks and RPC calls
optionally rendered by server_info and server_state, and
optionally printed to a distinct log file.
- Tally each Job Queue task as it is queued, starts, and
finishes running. Track total duration queued and running.
- Tally each RPC call as it starts and either finishes
successfully or throws an exception. Track total running
duration for each.
* Track currently executing Job Queue tasks and RPC methods
along with durations.
* Json-formatted performance log file written by a dedicated
thread, for above-described data.
* New optional parameter, "counters", for server_info and
server_state. If set, render Job Queue and RPC call counters
as well as currently executing tasks.
* New configuration section, "[perf]", to optionally control
performance logging to a file.
* Support optional sub-second periods when rendering human-readable
time points.
This commit is contained in:
committed by
Nikolaos D. Bougalis
parent
ef3bc92b82
commit
8eb8c77886
@@ -55,48 +55,7 @@ Status handle (Context& context, Object& object)
|
||||
return status;
|
||||
};
|
||||
|
||||
class HandlerTable {
|
||||
public:
|
||||
template<std::size_t N>
|
||||
explicit
|
||||
HandlerTable (const Handler(&entries)[N])
|
||||
{
|
||||
for (std::size_t i = 0; i < N; ++i)
|
||||
{
|
||||
auto const& entry = entries[i];
|
||||
assert (table_.find(entry.name_) == table_.end());
|
||||
table_[entry.name_] = entry;
|
||||
}
|
||||
|
||||
// This is where the new-style handlers are added.
|
||||
addHandler<LedgerHandler>();
|
||||
addHandler<VersionHandler>();
|
||||
}
|
||||
|
||||
const Handler* getHandler(std::string name) const {
|
||||
auto i = table_.find(name);
|
||||
return i == table_.end() ? nullptr : &i->second;
|
||||
}
|
||||
|
||||
private:
|
||||
std::map<std::string, Handler> table_;
|
||||
|
||||
template <class HandlerImpl>
|
||||
void addHandler()
|
||||
{
|
||||
assert (table_.find(HandlerImpl::name()) == table_.end());
|
||||
|
||||
Handler h;
|
||||
h.name_ = HandlerImpl::name();
|
||||
h.valueMethod_ = &handle<Json::Value, HandlerImpl>;
|
||||
h.role_ = HandlerImpl::role();
|
||||
h.condition_ = HandlerImpl::condition();
|
||||
|
||||
table_[HandlerImpl::name()] = h;
|
||||
};
|
||||
};
|
||||
|
||||
Handler handlerArray[] {
|
||||
Handler const handlerArray[] {
|
||||
// Some handlers not specified here are added to the table via addHandler()
|
||||
// Request-response methods
|
||||
{ "account_info", byRef (&doAccountInfo), Role::USER, NO_CONDITION },
|
||||
@@ -159,12 +118,77 @@ Handler handlerArray[] {
|
||||
{ "unsubscribe", byRef (&doUnsubscribe), Role::USER, NO_CONDITION },
|
||||
};
|
||||
|
||||
class HandlerTable {
|
||||
private:
|
||||
template<std::size_t N>
|
||||
explicit
|
||||
HandlerTable (const Handler(&entries)[N])
|
||||
{
|
||||
for (std::size_t i = 0; i < N; ++i)
|
||||
{
|
||||
auto const& entry = entries[i];
|
||||
assert (table_.find(entry.name_) == table_.end());
|
||||
table_[entry.name_] = entry;
|
||||
}
|
||||
|
||||
// This is where the new-style handlers are added.
|
||||
addHandler<LedgerHandler>();
|
||||
addHandler<VersionHandler>();
|
||||
}
|
||||
|
||||
public:
|
||||
static HandlerTable const& instance()
|
||||
{
|
||||
static HandlerTable const handlerTable (handlerArray);
|
||||
return handlerTable;
|
||||
}
|
||||
|
||||
Handler const* getHandler(std::string name) const
|
||||
{
|
||||
auto i = table_.find(name);
|
||||
return i == table_.end() ? nullptr : &i->second;
|
||||
}
|
||||
|
||||
std::vector<char const*>
|
||||
getHandlerNames() const
|
||||
{
|
||||
std::vector<char const*> ret;
|
||||
ret.reserve(table_.size());
|
||||
for (auto const& i : table_)
|
||||
ret.push_back(i.second.name_);
|
||||
return ret;
|
||||
}
|
||||
|
||||
private:
|
||||
std::map<std::string, Handler> table_;
|
||||
|
||||
template <class HandlerImpl>
|
||||
void addHandler()
|
||||
{
|
||||
assert (table_.find(HandlerImpl::name()) == table_.end());
|
||||
|
||||
Handler h;
|
||||
h.name_ = HandlerImpl::name();
|
||||
h.valueMethod_ = &handle<Json::Value, HandlerImpl>;
|
||||
h.role_ = HandlerImpl::role();
|
||||
h.condition_ = HandlerImpl::condition();
|
||||
|
||||
table_[HandlerImpl::name()] = h;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
const Handler* getHandler(std::string const& name) {
|
||||
static HandlerTable const handlers(handlerArray);
|
||||
return handlers.getHandler(name);
|
||||
Handler const* getHandler(std::string const& name)
|
||||
{
|
||||
return HandlerTable::instance().getHandler(name);
|
||||
}
|
||||
|
||||
std::vector<char const*>
|
||||
getHandlerNames()
|
||||
{
|
||||
return HandlerTable::instance().getHandlerNames();
|
||||
};
|
||||
|
||||
} // RPC
|
||||
} // ripple
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <ripple/core/Config.h>
|
||||
#include <ripple/rpc/RPCHandler.h>
|
||||
#include <ripple/rpc/Status.h>
|
||||
#include <vector>
|
||||
|
||||
namespace Json {
|
||||
class Object;
|
||||
@@ -50,7 +51,7 @@ struct Handler
|
||||
RPC::Condition condition_;
|
||||
};
|
||||
|
||||
const Handler* getHandler (std::string const&);
|
||||
Handler const* getHandler (std::string const&);
|
||||
|
||||
/** Return a Json::objectValue with a single entry. */
|
||||
template <class Value>
|
||||
@@ -62,6 +63,9 @@ Json::Value makeObjectValue (
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Return names of all methods. */
|
||||
std::vector<char const*> getHandlerNames();
|
||||
|
||||
} // RPC
|
||||
} // ripple
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <ripple/app/misc/NetworkOPs.h>
|
||||
#include <ripple/basics/contract.h>
|
||||
#include <ripple/basics/Log.h>
|
||||
#include <ripple/basics/PerfLog.h>
|
||||
#include <ripple/core/Config.h>
|
||||
#include <ripple/core/JobQueue.h>
|
||||
#include <ripple/json/Object.h>
|
||||
@@ -36,6 +37,8 @@
|
||||
#include <ripple/resource/Fees.h>
|
||||
#include <ripple/rpc/Role.h>
|
||||
#include <ripple/resource/Fees.h>
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
|
||||
namespace ripple {
|
||||
namespace RPC {
|
||||
@@ -197,14 +200,22 @@ template <class Object, class Method>
|
||||
Status callMethod (
|
||||
Context& context, Method method, std::string const& name, Object& result)
|
||||
{
|
||||
static std::atomic<std::uint64_t> requestId {0};
|
||||
auto& perfLog = context.app.getPerfLog();
|
||||
std::uint64_t const curId = ++requestId;
|
||||
try
|
||||
{
|
||||
perfLog.rpcStart(name, curId);
|
||||
auto v = context.app.getJobQueue().makeLoadEvent(
|
||||
jtGENERIC, "cmd:" + name);
|
||||
return method (context, result);
|
||||
|
||||
auto ret = method (context, result);
|
||||
perfLog.rpcFinish(name, curId);
|
||||
return ret;
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
perfLog.rpcError(name, curId);
|
||||
JLOG (context.j.info()) << "Caught throw: " << e.what ();
|
||||
|
||||
if (context.loadType == Resource::feeReferenceRPC)
|
||||
|
||||
Reference in New Issue
Block a user