mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-02-08 10:31:50 -05:00
rpc: make it possible to aggregate the result in getnetmsgstats
Aggregation can be by either one of direction, network, connection type or message type. For example if the following ``` { "ipv4": { "ping": 3 }, "ipv6": { "ping": 4 } } ``` is aggregated by network, then the result will be ``` { "ping": 7 } ```
This commit is contained in:
parent
033aa12a71
commit
0978d7d050
2 changed files with 84 additions and 29 deletions
|
@ -253,6 +253,7 @@ static const CRPCConvertParam vRPCConvertParams[] =
|
|||
{ "verifychain", 1, "nblocks" },
|
||||
{ "getblockstats", 0, "hash_or_height" },
|
||||
{ "getblockstats", 1, "stats" },
|
||||
{ "getnetmsgstats", 0, "aggregate_by"},
|
||||
{ "pruneblockchain", 0, "height" },
|
||||
{ "keypoolrefill", 0, "newsize" },
|
||||
{ "getrawmempool", 0, "verbose" },
|
||||
|
|
112
src/rpc/net.cpp
112
src/rpc/net.cpp
|
@ -548,11 +548,44 @@ static RPCHelpMan getaddednodeinfo()
|
|||
|
||||
namespace net_stats {
|
||||
|
||||
namespace aggregate_dimensions {
|
||||
static std::string DIRECTION{"direction"};
|
||||
static std::string NETWORK{"network"};
|
||||
static std::string CONNECTION_TYPE{"connection_type"};
|
||||
static std::string MESSAGE_TYPE{"message_type"};
|
||||
};
|
||||
|
||||
UniValue CreateJSON(const RPCHelpMan&, const JSONRPCRequest& request)
|
||||
{
|
||||
const NodeContext& node = EnsureAnyNodeContext(request.context);
|
||||
const CConnman& connman = EnsureConnman(node);
|
||||
|
||||
// Used for a quick check if a string is in request.params[0] which is
|
||||
// supposed to be a JSON array, e.g. ["direction", "network"].
|
||||
std::unordered_set<std::string> aggregate_by;
|
||||
if (request.params[0].isArray()) {
|
||||
const UniValue& arr{request.params[0].get_array()};
|
||||
for (size_t i = 0; i < arr.size(); ++i) {
|
||||
const auto& agg{arr[i].get_str()};
|
||||
if (agg != aggregate_dimensions::DIRECTION &&
|
||||
agg != aggregate_dimensions::NETWORK &&
|
||||
agg != aggregate_dimensions::CONNECTION_TYPE &&
|
||||
agg != aggregate_dimensions::MESSAGE_TYPE) {
|
||||
throw JSONRPCError(
|
||||
RPC_INVALID_PARAMS,
|
||||
strprintf(
|
||||
R"(Unrecognized aggregation parameter: "%s". The array should consist of zero or more of "%s", "%s", "%s", "%s".)",
|
||||
agg,
|
||||
aggregate_dimensions::DIRECTION,
|
||||
aggregate_dimensions::NETWORK,
|
||||
aggregate_dimensions::CONNECTION_TYPE,
|
||||
aggregate_dimensions::MESSAGE_TYPE));
|
||||
}
|
||||
aggregate_by.insert(agg);
|
||||
}
|
||||
}
|
||||
|
||||
// The keys might as well be an empty string (if aggregating by that dimension).
|
||||
std::unordered_map<
|
||||
std::string, // "sent" or "recv"
|
||||
std::unordered_map<std::string, // "ipv4", "tor", ...
|
||||
|
@ -561,22 +594,27 @@ UniValue CreateJSON(const RPCHelpMan&, const JSONRPCRequest& request)
|
|||
NetStats::BytesAndCount>>>>
|
||||
result_map;
|
||||
|
||||
connman.GetNetStats().ForEach([&result_map](NetStats::Direction dir,
|
||||
Network net,
|
||||
ConnectionType con,
|
||||
const std::string& msg,
|
||||
const NetStats::BytesAndCount& data) {
|
||||
const std::string dir_str{dir == NetStats::SENT ? "sent" : "recv"};
|
||||
const std::string net_str{GetNetworkName(net)};
|
||||
const std::string con_str{ConnectionTypeAsString(con)};
|
||||
connman.GetNetStats().ForEach([&aggregate_by, &result_map](NetStats::Direction dir,
|
||||
Network net,
|
||||
ConnectionType con,
|
||||
const std::string& msg,
|
||||
const NetStats::BytesAndCount& data) {
|
||||
const std::string dir_str{aggregate_by.contains(aggregate_dimensions::DIRECTION) ? "" : dir == NetStats::SENT ? "sent" : "recv"};
|
||||
const std::string net_str{aggregate_by.contains(aggregate_dimensions::NETWORK) ? "" : GetNetworkName(net)};
|
||||
const std::string con_str{aggregate_by.contains(aggregate_dimensions::CONNECTION_TYPE) ? "" : ConnectionTypeAsString(con)};
|
||||
const std::string msg_str{aggregate_by.contains(aggregate_dimensions::MESSAGE_TYPE) ? "" : msg};
|
||||
|
||||
result_map[dir_str][net_str][con_str][msg] += data;
|
||||
result_map[dir_str][net_str][con_str][msg_str] += data;
|
||||
});
|
||||
|
||||
auto Add = [](UniValue& target, const std::string& key, const UniValue& val) {
|
||||
if (val.empty()) {
|
||||
return;
|
||||
}
|
||||
if (key.empty()) {
|
||||
target = val;
|
||||
return;
|
||||
}
|
||||
target.pushKV(key, val);
|
||||
};
|
||||
|
||||
|
@ -614,8 +652,29 @@ static RPCHelpMan getnetmsgstats()
|
|||
{
|
||||
return RPCHelpMan{
|
||||
"getnetmsgstats",
|
||||
"\nReturns the messages count and total number of bytes for network traffic.\n",
|
||||
{},
|
||||
"\nReturns the messages count and total number of bytes for network traffic.\n"
|
||||
"Results may optionally be aggregated.\n",
|
||||
{RPCArg{
|
||||
"aggregate_by",
|
||||
RPCArg::Type::ARR,
|
||||
RPCArg::DefaultHint{"empty, no aggregation"},
|
||||
"An array of keywords for aggregating the results.",
|
||||
{RPCArg{"direction",
|
||||
RPCArg::Type::STR,
|
||||
RPCArg::Optional::OMITTED,
|
||||
"Aggregate by direction and don't show direction in the result."},
|
||||
RPCArg{"network",
|
||||
RPCArg::Type::STR,
|
||||
RPCArg::Optional::OMITTED,
|
||||
"Aggregate by network and don't show network in the result."},
|
||||
RPCArg{"connection_type",
|
||||
RPCArg::Type::STR,
|
||||
RPCArg::Optional::OMITTED,
|
||||
"Aggregate by connection type and don't show connection type in the result."},
|
||||
RPCArg{"message_type",
|
||||
RPCArg::Type::STR,
|
||||
RPCArg::Optional::OMITTED,
|
||||
"Aggregate by message type and don't show message type in the result."}}}},
|
||||
{RPCResult{
|
||||
RPCResult::Type::OBJ_DYN,
|
||||
"",
|
||||
|
@ -638,29 +697,24 @@ static RPCHelpMan getnetmsgstats()
|
|||
"inbound",
|
||||
true,
|
||||
"The connection type over which the traffic occurred.",
|
||||
{RPCResult{RPCResult::Type::OBJ,
|
||||
"verack",
|
||||
true,
|
||||
"Type of the messages transferred.",
|
||||
{RPCResult{RPCResult::Type::NUM,
|
||||
"bytes",
|
||||
false,
|
||||
"Total number of bytes.",
|
||||
{},
|
||||
true},
|
||||
RPCResult{RPCResult::Type::NUM,
|
||||
"count",
|
||||
false,
|
||||
"Total number of messages.",
|
||||
{},
|
||||
true}},
|
||||
true}},
|
||||
{RPCResult{
|
||||
RPCResult::Type::OBJ,
|
||||
"verack",
|
||||
true,
|
||||
"Type of the messages transferred.",
|
||||
{
|
||||
RPCResult{RPCResult::Type::NUM, "bytes", false, "Total number of bytes.", {}, true},
|
||||
RPCResult{RPCResult::Type::NUM, "count", false, "Total number of messages.", {}, true}
|
||||
},
|
||||
true}},
|
||||
true}},
|
||||
true}},
|
||||
true}},
|
||||
true}},
|
||||
RPCExamples{HelpExampleCli("getnetmsgstats", "") +
|
||||
HelpExampleRpc("getnetmsgstats", "")},
|
||||
HelpExampleCli("getnetmsgstats", R"('["network", "message_type"]')") +
|
||||
HelpExampleRpc("getnetmsgstats", "") +
|
||||
HelpExampleRpc("getnetmsgstats", R"(["network", "message_type"])")},
|
||||
net_stats::CreateJSON};
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue