Skip to content

Commit

Permalink
rpc: create a new getnetmsgstats rpc
Browse files Browse the repository at this point in the history
Introduce a new getnetmsgstats rpc that is able to return network
message statistics arranged in a number of different ways (direction,
network, connection, message type). If no dimension types are
specified to be shown, return the totals.

Includes helper code to convert a string to a DimensionType enum.

Co-authored-by: Vasil Dimov <[email protected]>
Co-authored-by: Will Clark <[email protected]>
  • Loading branch information
3 people committed Nov 22, 2023
1 parent 2250699 commit b352853
Show file tree
Hide file tree
Showing 2 changed files with 115 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/rpc/client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,7 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "verifychain", 1, "nblocks" },
{ "getblockstats", 0, "hash_or_height" },
{ "getblockstats", 1, "stats" },
{ "getnetmsgstats", 0, "group_by"},
{ "pruneblockchain", 0, "height" },
{ "keypoolrefill", 0, "newsize" },
{ "getrawmempool", 0, "verbose" },
Expand Down
114 changes: 114 additions & 0 deletions src/rpc/net.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -746,8 +746,121 @@ UniValue Aggregate(const std::vector<DimensionType>& dimensions, const NetStats:
return result.to_univalue();
}

static std::vector<RPCResult> NetMsgStat()
{
return {
{RPCResult::Type::NUM, "message_count", "Total number of messages sent"},
{RPCResult::Type::NUM, "byte_count", "Total number of bytes sent"}};
}
}; // namespace net_stats

static RPCHelpMan getnetmsgstats()
{
return RPCHelpMan{
"getnetmsgstats",
"\nReturns the message count and total number of bytes for network traffic.\n"
"Results may optionally be grouped so only certain dimensions are shown."
"\nWhen a message, connection, network type, or direction is not listed\n"
"in the result the statistics for that type are 0. Only known message,\n"
"connection, and network types can appear as keys in the object.",
{{"group_by",
RPCArg::Type::ARR,
RPCArg::Optional::OMITTED,
"An array of dimensions to arrange results by.",
{{"dimension_type",
RPCArg::Type::STR,
RPCArg::Optional::OMITTED,
"Dimension type to arrange results by.\n"
"Valid options are: direction, network, connection_type, and message_type"}}}},
{
// A return object with one level of data: either when totals are returned (no dimensions),
// or one dimension has been specified
RPCResult{
RPCResult::Type::OBJ_DYN,
"",
"",
{{RPCResult::Type::OBJ,
"totals",
true,
"Network traffic statistics.\n",
net_stats::NetMsgStat()},
{RPCResult::Type::OBJ_DYN,
"keys for the dimension type",
true,
"Network traffic statistics.\n",
net_stats::NetMsgStat()}}},
// A return object with two levels of data: two dimensions
RPCResult{
RPCResult::Type::OBJ_DYN,
"",
"",
{{RPCResult::Type::OBJ_DYN,
"keys for the first dimension type",
"Network traffic statistics.\n",
{{RPCResult::Type::OBJ_DYN,
"keys for the second dimension type",
"",
net_stats::NetMsgStat()}}}}},
// A return object with three levels of data: three dimensions
RPCResult{
RPCResult::Type::OBJ_DYN,
"",
"",
{{RPCResult::Type::OBJ_DYN,
"keys for the first dimension type",
"Network traffic statistics.\n",
{{RPCResult::Type::OBJ_DYN,
"keys for the second dimension type",
"",
{{RPCResult::Type::OBJ_DYN,
"keys for the third dimension type",
"",
net_stats::NetMsgStat()}}}}}}},
// A return object with four levels of data: four dimensions
RPCResult{
RPCResult::Type::OBJ_DYN,
"",
"",
{{RPCResult::Type::OBJ_DYN,
"keys for the first dimension type",
"Network traffic statistics.\n",
{{RPCResult::Type::OBJ_DYN,
"keys for the second dimension type",
"",
{{RPCResult::Type::OBJ_DYN,
"keys for the third dimension type",
"",
{{RPCResult::Type::OBJ_DYN,
"keys for the fourth dimension type",
"",
net_stats::NetMsgStat()}}}}}}}}}},

RPCExamples{
HelpExampleCli("getnetmsgstats", "") +
HelpExampleCli("getnetmsgstats", R"('["connection_type","message_type"]')") +
HelpExampleRpc("getnetmsgstats", "") +
HelpExampleRpc("getnetmsgstats", R"(["message_type","network"])")},
/*fun=*/[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue {
NodeContext& node = EnsureAnyNodeContext(request.context);
const CConnman& connman = EnsureConnman(node);
std::vector<net_stats::DimensionType> dimensions;

// Aggregate the messages to show only requested dimensions
if (request.params[0].isArray()) {
const UniValue raw_dimensions = request.params[0].get_array();

for (unsigned int i = 0; i < raw_dimensions.size(); ++i) {
std::string dimension_string = raw_dimensions[i].get_str();
net_stats::DimensionType dimension = net_stats::StringToDimensionType(dimension_string);
dimensions.push_back(dimension);
}
}

UniValue obj = net_stats::Aggregate(dimensions, connman.GetNetStats().m_data);
return obj;
}};
}

static RPCHelpMan getnettotals()
{
return RPCHelpMan{"getnettotals",
Expand Down Expand Up @@ -1364,6 +1477,7 @@ void RegisterNetRPCCommands(CRPCTable& t)
{"network", &addnode},
{"network", &disconnectnode},
{"network", &getaddednodeinfo},
{"network", &getnetmsgstats},
{"network", &getnettotals},
{"network", &getnetworkinfo},
{"network", &setban},
Expand Down

0 comments on commit b352853

Please sign in to comment.