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" },
|
{ "verifychain", 1, "nblocks" },
|
||||||
{ "getblockstats", 0, "hash_or_height" },
|
{ "getblockstats", 0, "hash_or_height" },
|
||||||
{ "getblockstats", 1, "stats" },
|
{ "getblockstats", 1, "stats" },
|
||||||
|
{ "getnetmsgstats", 0, "aggregate_by"},
|
||||||
{ "pruneblockchain", 0, "height" },
|
{ "pruneblockchain", 0, "height" },
|
||||||
{ "keypoolrefill", 0, "newsize" },
|
{ "keypoolrefill", 0, "newsize" },
|
||||||
{ "getrawmempool", 0, "verbose" },
|
{ "getrawmempool", 0, "verbose" },
|
||||||
|
|
112
src/rpc/net.cpp
112
src/rpc/net.cpp
|
@ -548,11 +548,44 @@ static RPCHelpMan getaddednodeinfo()
|
||||||
|
|
||||||
namespace net_stats {
|
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)
|
UniValue CreateJSON(const RPCHelpMan&, const JSONRPCRequest& request)
|
||||||
{
|
{
|
||||||
const NodeContext& node = EnsureAnyNodeContext(request.context);
|
const NodeContext& node = EnsureAnyNodeContext(request.context);
|
||||||
const CConnman& connman = EnsureConnman(node);
|
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::unordered_map<
|
||||||
std::string, // "sent" or "recv"
|
std::string, // "sent" or "recv"
|
||||||
std::unordered_map<std::string, // "ipv4", "tor", ...
|
std::unordered_map<std::string, // "ipv4", "tor", ...
|
||||||
|
@ -561,22 +594,27 @@ UniValue CreateJSON(const RPCHelpMan&, const JSONRPCRequest& request)
|
||||||
NetStats::BytesAndCount>>>>
|
NetStats::BytesAndCount>>>>
|
||||||
result_map;
|
result_map;
|
||||||
|
|
||||||
connman.GetNetStats().ForEach([&result_map](NetStats::Direction dir,
|
connman.GetNetStats().ForEach([&aggregate_by, &result_map](NetStats::Direction dir,
|
||||||
Network net,
|
Network net,
|
||||||
ConnectionType con,
|
ConnectionType con,
|
||||||
const std::string& msg,
|
const std::string& msg,
|
||||||
const NetStats::BytesAndCount& data) {
|
const NetStats::BytesAndCount& data) {
|
||||||
const std::string dir_str{dir == NetStats::SENT ? "sent" : "recv"};
|
const std::string dir_str{aggregate_by.contains(aggregate_dimensions::DIRECTION) ? "" : dir == NetStats::SENT ? "sent" : "recv"};
|
||||||
const std::string net_str{GetNetworkName(net)};
|
const std::string net_str{aggregate_by.contains(aggregate_dimensions::NETWORK) ? "" : GetNetworkName(net)};
|
||||||
const std::string con_str{ConnectionTypeAsString(con)};
|
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) {
|
auto Add = [](UniValue& target, const std::string& key, const UniValue& val) {
|
||||||
if (val.empty()) {
|
if (val.empty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (key.empty()) {
|
||||||
|
target = val;
|
||||||
|
return;
|
||||||
|
}
|
||||||
target.pushKV(key, val);
|
target.pushKV(key, val);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -614,8 +652,29 @@ static RPCHelpMan getnetmsgstats()
|
||||||
{
|
{
|
||||||
return RPCHelpMan{
|
return RPCHelpMan{
|
||||||
"getnetmsgstats",
|
"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{
|
||||||
RPCResult::Type::OBJ_DYN,
|
RPCResult::Type::OBJ_DYN,
|
||||||
"",
|
"",
|
||||||
|
@ -638,29 +697,24 @@ static RPCHelpMan getnetmsgstats()
|
||||||
"inbound",
|
"inbound",
|
||||||
true,
|
true,
|
||||||
"The connection type over which the traffic occurred.",
|
"The connection type over which the traffic occurred.",
|
||||||
{RPCResult{RPCResult::Type::OBJ,
|
{RPCResult{
|
||||||
"verack",
|
RPCResult::Type::OBJ,
|
||||||
true,
|
"verack",
|
||||||
"Type of the messages transferred.",
|
true,
|
||||||
{RPCResult{RPCResult::Type::NUM,
|
"Type of the messages transferred.",
|
||||||
"bytes",
|
{
|
||||||
false,
|
RPCResult{RPCResult::Type::NUM, "bytes", false, "Total number of bytes.", {}, true},
|
||||||
"Total number of bytes.",
|
RPCResult{RPCResult::Type::NUM, "count", false, "Total number of messages.", {}, true}
|
||||||
{},
|
},
|
||||||
true},
|
true}},
|
||||||
RPCResult{RPCResult::Type::NUM,
|
|
||||||
"count",
|
|
||||||
false,
|
|
||||||
"Total number of messages.",
|
|
||||||
{},
|
|
||||||
true}},
|
|
||||||
true}},
|
|
||||||
true}},
|
true}},
|
||||||
true}},
|
true}},
|
||||||
true}},
|
true}},
|
||||||
true}},
|
true}},
|
||||||
RPCExamples{HelpExampleCli("getnetmsgstats", "") +
|
RPCExamples{HelpExampleCli("getnetmsgstats", "") +
|
||||||
HelpExampleRpc("getnetmsgstats", "")},
|
HelpExampleCli("getnetmsgstats", R"('["network", "message_type"]')") +
|
||||||
|
HelpExampleRpc("getnetmsgstats", "") +
|
||||||
|
HelpExampleRpc("getnetmsgstats", R"(["network", "message_type"])")},
|
||||||
net_stats::CreateJSON};
|
net_stats::CreateJSON};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue