diff --git a/nano/lib/stats_enums.hpp b/nano/lib/stats_enums.hpp index 429741d2f3..630e0d1ea0 100644 --- a/nano/lib/stats_enums.hpp +++ b/nano/lib/stats_enums.hpp @@ -26,7 +26,9 @@ enum class type election, election_cleanup, election_vote, - http_callback, + http_callbacks, + http_callbacks_notified, + http_callbacks_ec, ipc, tcp, tcp_server, @@ -166,6 +168,8 @@ enum class detail other, drop, queued, + error, + failed, // processing queue queue, @@ -625,6 +629,16 @@ enum class detail host_unreachable, not_supported, + // http + error_resolving, + error_connecting, + error_sending, + error_completing, + bad_status, + + // http_callbacks + block_confirmed, + _last // Must be the last enum }; diff --git a/nano/node/rpc_callbacks.cpp b/nano/node/rpc_callbacks.cpp index 08b95b1c95..ea5ab4c27a 100644 --- a/nano/node/rpc_callbacks.cpp +++ b/nano/node/rpc_callbacks.cpp @@ -33,6 +33,8 @@ void nano::http_callbacks::setup_callbacks () // Only process blocks that have achieved quorum or confirmation height if ((status_a.type == nano::election_status_type::active_confirmed_quorum || status_a.type == nano::election_status_type::active_confirmation_height)) { + stats.inc (nano::stat::type::http_callbacks_notified, nano::stat::detail::block_confirmed); + // Post callback processing to worker thread // Safe to capture 'this' by reference as workers are stopped before node destruction node.workers.post ([this, block_a, account_a, amount_a, is_state_send_a, is_state_epoch_a] () { @@ -93,8 +95,10 @@ void nano::http_callbacks::setup_callbacks () } else { + stats.inc (nano::stat::type::http_callbacks, nano::stat::detail::error_resolving); + stats.inc (nano::stat::type::http_callbacks_ec, to_stat_detail (ec)); + logger.error (nano::log::type::http_callbacks, "Error resolving callback: {}:{} ({})", address, port, ec.message ()); - stats.inc (nano::stat::type::error, nano::stat::detail::http_callback, nano::stat::dir::out); } }); }); @@ -117,6 +121,8 @@ std::shared_ptr const & resolver) // Check if we have more endpoints to try if (i_a != boost::asio::ip::tcp::resolver::iterator{}) { + stats.inc (nano::stat::type::http_callbacks, nano::stat::detail::initiate); + // Create socket and attempt connection auto sock = std::make_shared (node.io_ctx); sock->async_connect (i_a->endpoint (), @@ -152,36 +158,42 @@ std::shared_ptr const & resolver) // Check response status if (boost::beast::http::to_status_class (resp->result ()) == boost::beast::http::status_class::successful) { - stats.inc (nano::stat::type::http_callback, nano::stat::detail::initiate, nano::stat::dir::out); + stats.inc (nano::stat::type::http_callbacks, nano::stat::detail::success); } else { + stats.inc (nano::stat::type::http_callbacks, nano::stat::detail::bad_status); + logger.error (nano::log::type::http_callbacks, "Callback to {}:{} failed [status: {}]", address, port, nano::util::to_str (resp->result ())); - stats.inc (nano::stat::type::error, nano::stat::detail::http_callback, nano::stat::dir::out); } } else { + stats.inc (nano::stat::type::http_callbacks, nano::stat::detail::error_completing); + stats.inc (nano::stat::type::http_callbacks_ec, to_stat_detail (ec)); + logger.error (nano::log::type::http_callbacks, "Unable to complete callback: {}:{} ({})", address, port, ec.message ()); - stats.inc (nano::stat::type::error, nano::stat::detail::http_callback, nano::stat::dir::out); } }); } else { + stats.inc (nano::stat::type::http_callbacks, nano::stat::detail::error_sending); + stats.inc (nano::stat::type::http_callbacks_ec, to_stat_detail (ec)); + logger.error (nano::log::type::http_callbacks, "Unable to send callback: {}:{} ({})", address, port, ec.message ()); - stats.inc (nano::stat::type::error, nano::stat::detail::http_callback, nano::stat::dir::out); } }); } - else + else // Connection failed, try next endpoint if available { - // Connection failed, try next endpoint if available + stats.inc (nano::stat::type::http_callbacks, nano::stat::detail::error_connecting); + stats.inc (nano::stat::type::http_callbacks_ec, to_stat_detail (ec)); + logger.error (nano::log::type::http_callbacks, "Unable to connect to callback address({}): {}:{} ({})", address, i_a->endpoint ().address ().to_string (), port, ec.message ()); - stats.inc (nano::stat::type::error, nano::stat::detail::http_callback, nano::stat::dir::out); ++i_a; do_rpc_callback (i_a, address, port, target, body, resolver); diff --git a/nano/rpc_test/rpc.cpp b/nano/rpc_test/rpc.cpp index 82c9837d5b..eecaf6430c 100644 --- a/nano/rpc_test/rpc.cpp +++ b/nano/rpc_test/rpc.cpp @@ -5252,7 +5252,7 @@ TEST (rpc, block_confirm_confirmed) auto transaction = node->ledger.tx_begin_read (); ASSERT_TRUE (node->ledger.confirmed.block_exists_or_pruned (transaction, nano::dev::genesis->hash ())); } - ASSERT_EQ (0, node->stats.count (nano::stat::type::error, nano::stat::detail::http_callback, nano::stat::dir::out)); + ASSERT_EQ (0, node->stats.count (nano::stat::type::http_callbacks_ec)); auto const rpc_ctx = add_rpc (system, node); boost::property_tree::ptree request; request.put ("action", "block_confirm"); @@ -5266,7 +5266,7 @@ TEST (rpc, block_confirm_confirmed) // Check callback // Callback result is error because callback target port isn't listening // Check for error count greater than zero as the address goes through DNS resolution and may make multiple attempts for multiple IPs per DNS - ASSERT_TIMELY (5s, node->stats.count (nano::stat::type::error, nano::stat::detail::http_callback, nano::stat::dir::out) != 0); + ASSERT_TIMELY (5s, node->stats.count (nano::stat::type::http_callbacks_ec) != 0); } TEST (rpc, node_id)