From c5d943ad827083aef5b9fcae4a840950212f1ade Mon Sep 17 00:00:00 2001 From: cryptocode Date: Tue, 29 Jan 2019 21:07:49 +0100 Subject: [PATCH] RPC to clear stats (#1625) * RPC to clear stats, and seconds since last clear * Add rpc.stats_clear tests * Add status check --- nano/core_test/rpc.cpp | 22 ++++++++++++++++++++++ nano/node/rpc.cpp | 15 ++++++++++++++- nano/node/rpc.hpp | 1 + nano/node/stats.cpp | 14 ++++++++++++++ nano/node/stats.hpp | 9 +++++++++ 5 files changed, 60 insertions(+), 1 deletion(-) diff --git a/nano/core_test/rpc.cpp b/nano/core_test/rpc.cpp index caed4360..442c6add 100644 --- a/nano/core_test/rpc.cpp +++ b/nano/core_test/rpc.cpp @@ -4168,6 +4168,28 @@ TEST (rpc, node_id_delete) ASSERT_NE (node_id.pub.to_string (), system.nodes[0]->node_id.pub.to_string ()); } +TEST (rpc, stats_clear) +{ + nano::system system (24000, 1); + nano::keypair key; + nano::rpc rpc (system.io_ctx, *system.nodes[0], nano::rpc_config (true)); + rpc.start (); + system.nodes[0]->stats.inc (nano::stat::type::ledger, nano::stat::dir::in); + ASSERT_EQ (1, system.nodes[0]->stats.count (nano::stat::type::ledger, nano::stat::dir::in)); + boost::property_tree::ptree request; + request.put ("action", "stats_clear"); + test_response response (request, rpc, system.io_ctx); + system.deadline_set (5s); + while (response.status == 0) + { + ASSERT_NO_ERROR (system.poll ()); + } + std::string success (response.json.get ("success")); + ASSERT_TRUE (success.empty ()); + ASSERT_EQ (0, system.nodes[0]->stats.count (nano::stat::type::ledger, nano::stat::dir::in)); + ASSERT_LE (system.nodes[0]->stats.last_reset ().count (), 5); +} + TEST (rpc, uptime) { nano::system system (24000, 1); diff --git a/nano/node/rpc.cpp b/nano/node/rpc.cpp index fed88452..8c3c7e0a 100644 --- a/nano/node/rpc.cpp +++ b/nano/node/rpc.cpp @@ -3100,7 +3100,9 @@ void nano::rpc_handler::stats () } if (!ec) { - response (*static_cast (sink->to_object ())); + auto stat_tree_l (*static_cast (sink->to_object ())); + stat_tree_l.put ("stat_duration_seconds", node.stats.last_reset ().count ()); + response (stat_tree_l); } else { @@ -3108,6 +3110,13 @@ void nano::rpc_handler::stats () } } +void nano::rpc_handler::stats_clear () +{ + node.stats.clear (); + response_l.put ("success", ""); + response (response_l); +} + void nano::rpc_handler::stop () { rpc_control_impl (); @@ -4450,6 +4459,10 @@ void nano::rpc_handler::process_request () { stats (); } + else if (action == "stats_clear") + { + stats_clear (); + } else if (action == "stop") { stop (); diff --git a/nano/node/rpc.hpp b/nano/node/rpc.hpp index 9c06de31..c787073e 100644 --- a/nano/node/rpc.hpp +++ b/nano/node/rpc.hpp @@ -199,6 +199,7 @@ public: void send (); void sign (); void stats (); + void stats_clear (); void stop (); void unchecked (); void unchecked_clear (); diff --git a/nano/node/stats.cpp b/nano/node/stats.cpp index 948907a5..ac0c3202 100644 --- a/nano/node/stats.cpp +++ b/nano/node/stats.cpp @@ -310,6 +310,20 @@ void nano::stat::update (uint32_t key_a, uint64_t value) } } +std::chrono::seconds nano::stat::last_reset () +{ + std::unique_lock lock (stat_mutex); + auto now (std::chrono::steady_clock::now ()); + return std::chrono::duration_cast (now - timestamp); +} + +void nano::stat::clear () +{ + std::unique_lock lock (stat_mutex); + entries.clear (); + timestamp = std::chrono::steady_clock::now (); +} + std::string nano::stat::type_to_string (uint32_t key) { auto type = static_cast (key >> 16 & 0x000000ff); diff --git a/nano/node/stats.hpp b/nano/node/stats.hpp index b038e4dc..f3a923e9 100644 --- a/nano/node/stats.hpp +++ b/nano/node/stats.hpp @@ -386,6 +386,12 @@ public: return get_entry (key_of (type, detail, dir))->counter.value; } + /** Returns the number of seconds since clear() was last called, or node startup if it's never called. */ + std::chrono::seconds last_reset (); + + /** Clear all stats */ + void clear (); + /** Log counters to the given log link */ void log_counters (stat_log_sink & sink); @@ -431,6 +437,9 @@ private: /** Unlocked implementation of log_samples() to avoid using recursive locking */ void log_samples_impl (stat_log_sink & sink); + /** Time of last clear() call */ + std::chrono::steady_clock::time_point timestamp{ std::chrono::steady_clock::now () }; + /** Configuration deserialized from config.json */ nano::stat_config config;