1#include <xrpld/perflog/detail/PerfLogImp.h>
3#include <xrpld/app/main/Application.h>
5#include <xrpl/basics/Log.h>
6#include <xrpl/basics/chrono.h>
7#include <xrpl/beast/core/CurrentThreadName.h>
8#include <xrpl/beast/utility/Journal.h>
9#include <xrpl/beast/utility/instrumentation.h>
10#include <xrpl/config/BasicConfig.h>
11#include <xrpl/config/Constants.h>
12#include <xrpl/core/Job.h>
13#include <xrpl/core/JobTypes.h>
14#include <xrpl/core/PerfLog.h>
15#include <xrpl/json/json_value.h>
16#include <xrpl/json/json_writer.h>
17#include <xrpl/nodestore/Database.h>
18#include <xrpl/protocol/jss.h>
44 auto const inserted =
rpc.emplace(label,
Rpc()).second;
50 "xrpl::perf::PerfLogImp::Counters::Counters : failed to "
58 jq.reserve(jobTypes.
size());
59 for (
auto const& [jobType, _] : jobTypes)
61 auto const inserted =
jq.emplace(jobType,
Jq()).second;
67 "xrpl::perf::PerfLogImp::Counters::Counters : failed to "
81 for (
auto const& proc :
rpc)
86 if ((proc.second.value.started == 0u) && (proc.second.value.finished == 0u) &&
87 (proc.second.value.errored == 0u))
91 value = proc.second.value;
96 totalRpc.
started += value.started;
100 totalRpc.
errored += value.errored;
102 totalRpc.
duration += value.duration;
103 rpcobj[proc.first] = p;
113 rpcobj[jss::total] = totalRpcJson;
119 for (
auto const& proc :
jq)
124 if ((proc.second.value.queued == 0u) && (proc.second.value.started == 0u) &&
125 (proc.second.value.finished == 0u))
129 value = proc.second.value;
134 totalJq.
queued += value.queued;
136 totalJq.
started += value.started;
139 j[jss::queued_duration_us] =
std::to_string(value.queuedDuration.count());
141 j[jss::running_duration_us] =
std::to_string(value.runningDuration.count());
154 jobQueueObj[jss::total] = totalJqJson;
160 counters[jss::rpc] = rpcobj;
161 counters[jss::job_queue] = jobQueueObj;
171 auto const jobs = [
this] {
176 for (
auto const& j :
jobs)
182 jobj[jss::duration_us] =
192 for (
auto const& m : this->methods)
198 methodobj[jss::method] = m.first;
199 methodobj[jss::duration_us] =
201 methodsArray.
append(methodobj);
205 current[jss::jobs] = jobsArray;
206 current[jss::methods] = methodsArray;
215 if (
setup_.perfLog.empty())
221 auto logDir =
setup_.perfLog.parent_path();
228 JLOG(
j_.fatal()) <<
"Unable to create performance log "
230 << logDir <<
": " << ec.
message();
236 logFile_.open(
setup_.perfLog.c_str(), std::ios::out | std::ios::app);
240 JLOG(
j_.fatal()) <<
"Unable to open performance log " <<
setup_.perfLog <<
".";
284 report[jss::time] =
to_string(std::chrono::floor<microseconds>(present));
287 report[jss::workers] =
static_cast<unsigned int>(
counters_.jobs.size());
292 app_.getNodeStore().getCountsJson(
report[jss::nodestore]);
317 auto counter =
counters_.rpc.find(method);
321 UNREACHABLE(
"xrpl::perf::PerfLogImp::rpcStart : valid method input");
328 ++counter->second.value.started;
337 auto counter =
counters_.rpc.find(method);
341 UNREACHABLE(
"xrpl::perf::PerfLogImp::rpcEnd : valid method input");
348 auto const e =
counters_.methods.find(requestId);
351 startTime = e->second.second;
357 UNREACHABLE(
"xrpl::perf::PerfLogImp::rpcEnd : valid requestId input");
364 ++counter->second.value.finished;
368 ++counter->second.value.errored;
370 counter->second.value.duration +=
381 UNREACHABLE(
"xrpl::perf::PerfLogImp::jobQueue : valid job type input");
386 ++counter->second.value.queued;
400 UNREACHABLE(
"xrpl::perf::PerfLogImp::jobStart : valid job type input");
407 ++counter->second.value.started;
408 counter->second.value.queuedDuration += dur;
411 if (instance >= 0 && instance <
counters_.jobs.size())
412 counters_.jobs[instance] = {type, startTime};
422 UNREACHABLE(
"xrpl::perf::PerfLogImp::jobFinish : valid job type input");
429 ++counter->second.value.finished;
430 counter->second.value.runningDuration += dur;
433 if (instance >= 0 && instance <
counters_.jobs.size())
448 if (
setup_.perfLog.empty())
459 if (!
setup_.perfLog.empty())
484 set(perfLog,
"perf_log", section);
485 if (!perfLog.
empty())
A generic endpoint for log messages.
Decorator for streaming out compact json.
Value & append(Value const &value)
Append value to array at the end.
Map::size_type size() const
static std::string const & name(JobType jt)
Holds a collection of configuration values.
std::condition_variable cond_
void jobFinish(JobType const type, microseconds dur, int instance) override
Log job finishing.
PerfLogImp(Setup setup, Application &app, beast::Journal journal, std::function< void()> &&signalStop)
void rpcStart(std::string const &method, std::uint64_t const requestId) override
Log start of RPC call.
void jobQueue(JobType const type) override
Log queued job.
void resizeJobs(int const resize) override
Ensure enough room to store each currently executing job.
system_time_point lastLog_
void rpcEnd(std::string const &method, std::uint64_t const requestId, bool finish)
void rotate() override
Rotate perf log file.
std::function< void()> const signalStop_
void jobStart(JobType const type, microseconds dur, steady_time_point startTime, int instance) override
Log job executing.
std::string const hostname_
std::chrono::microseconds microseconds
std::chrono::time_point< steady_clock > steady_time_point
T create_directories(T... args)
T duration_cast(T... args)
T is_directory(T... args)
void setCurrentThreadName(std::string_view newThreadName)
Changes the name of the caller thread.
@ Array
array value (ordered list)
@ Object
object value (collection of name/value pairs).
Dummy class for unit tests.
std::unique_ptr< PerfLog > makePerfLog(PerfLog::Setup const &setup, Application &app, beast::Journal journal, std::function< void()> &&signalStop)
PerfLog::Setup setupPerfLog(Section const §ion, std::filesystem::path const &configDir)
bool set(T &target, std::string const &name, Section const §ion)
Set a value from a configuration Section If the named value is not found or doesn't parse as a T,...
bool getIfExists(Section const §ion, std::string const &name, T &v)
std::string to_string(BaseUInt< Bits, Tag > const &a)
static constexpr auto kLogInterval
Job Queue task performance counters.
microseconds queuedDuration
microseconds runningDuration
RPC performance counters.
std::vector< std::pair< JobType, steady_time_point > > jobs
std::unordered_map< std::string, Locked< Rpc > > rpc
json::Value countersJson() const
json::Value currentJson() const
Counters(std::set< char const * > const &labels, JobTypes const &jobTypes)
std::unordered_map< JobType, Locked< Jq > > jq
std::unordered_map< std::uint64_t, MethodStart > methods
Configuration from [perf] section of xrpld.cfg.
std::filesystem::path perfLog