From f81951dd00f11d860ef9c249680d27506b19a706 Mon Sep 17 00:00:00 2001 From: Kittywhiskers Van Gogh <63189531+kwvg@users.noreply.github.com> Date: Mon, 2 Sep 2024 11:56:07 +0000 Subject: [PATCH 01/13] stats: make `statsClient` a `std::unique_ptr`, denote as global variable This step is needed so we can simplify construction in an upcoming commit --- src/init.cpp | 38 +++++++++++++++----------- src/net.cpp | 40 +++++++++++++-------------- src/net_processing.cpp | 10 +++---- src/statsd_client.cpp | 2 +- src/statsd_client.h | 2 +- src/test/util/setup_common.cpp | 3 ++ src/txorphanage.cpp | 8 +++--- src/validation.cpp | 50 +++++++++++++++++----------------- 8 files changed, 81 insertions(+), 72 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 1bd565b760..9e616b5e5b 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -289,6 +289,7 @@ void PrepareShutdown(NodeContext& node) node.banman.reset(); node.addrman.reset(); node.netgroupman.reset(); + ::statsClient.reset(); if (node.mempool && node.mempool->IsLoaded() && node.args->GetBoolArg("-persistmempool", DEFAULT_PERSIST_MEMPOOL)) { DumpMempool(*node.mempool); @@ -839,12 +840,12 @@ static void PeriodicStats(ArgsManager& args, ChainstateManager& chainman, const CCoinsStats stats{CoinStatsHashType::NONE}; chainman.ActiveChainstate().ForceFlushStateToDisk(); if (WITH_LOCK(cs_main, return GetUTXOStats(&chainman.ActiveChainstate().CoinsDB(), std::ref(chainman.m_blockman), stats, RpcInterruptionPoint, chainman.ActiveChain().Tip()))) { - statsClient.gauge("utxoset.tx", stats.nTransactions, 1.0f); - statsClient.gauge("utxoset.txOutputs", stats.nTransactionOutputs, 1.0f); - statsClient.gauge("utxoset.dbSizeBytes", stats.nDiskSize, 1.0f); - statsClient.gauge("utxoset.blockHeight", stats.nHeight, 1.0f); + ::statsClient->gauge("utxoset.tx", stats.nTransactions, 1.0f); + ::statsClient->gauge("utxoset.txOutputs", stats.nTransactionOutputs, 1.0f); + ::statsClient->gauge("utxoset.dbSizeBytes", stats.nDiskSize, 1.0f); + ::statsClient->gauge("utxoset.blockHeight", stats.nHeight, 1.0f); if (stats.total_amount.has_value()) { - statsClient.gauge("utxoset.totalAmount", (double)stats.total_amount.value() / (double)COIN, 1.0f); + ::statsClient->gauge("utxoset.totalAmount", (double)stats.total_amount.value() / (double)COIN, 1.0f); } } else { // something went wrong @@ -866,22 +867,22 @@ static void PeriodicStats(ArgsManager& args, ChainstateManager& chainman, const int64_t timeDiff = maxTime - minTime; double nNetworkHashPS = workDiff.getdouble() / timeDiff; - statsClient.gaugeDouble("network.hashesPerSecond", nNetworkHashPS); - statsClient.gaugeDouble("network.terahashesPerSecond", nNetworkHashPS / 1e12); - statsClient.gaugeDouble("network.petahashesPerSecond", nNetworkHashPS / 1e15); - statsClient.gaugeDouble("network.exahashesPerSecond", nNetworkHashPS / 1e18); + ::statsClient->gaugeDouble("network.hashesPerSecond", nNetworkHashPS); + ::statsClient->gaugeDouble("network.terahashesPerSecond", nNetworkHashPS / 1e12); + ::statsClient->gaugeDouble("network.petahashesPerSecond", nNetworkHashPS / 1e15); + ::statsClient->gaugeDouble("network.exahashesPerSecond", nNetworkHashPS / 1e18); // No need for cs_main, we never use null tip here - statsClient.gaugeDouble("network.difficulty", (double)GetDifficulty(tip)); + ::statsClient->gaugeDouble("network.difficulty", (double)GetDifficulty(tip)); - statsClient.gauge("transactions.txCacheSize", WITH_LOCK(cs_main, return chainman.ActiveChainstate().CoinsTip().GetCacheSize()), 1.0f); - statsClient.gauge("transactions.totalTransactions", tip->nChainTx, 1.0f); + ::statsClient->gauge("transactions.txCacheSize", WITH_LOCK(cs_main, return chainman.ActiveChainstate().CoinsTip().GetCacheSize()), 1.0f); + ::statsClient->gauge("transactions.totalTransactions", tip->nChainTx, 1.0f); { LOCK(mempool.cs); - statsClient.gauge("transactions.mempool.totalTransactions", mempool.size(), 1.0f); - statsClient.gauge("transactions.mempool.totalTxBytes", (int64_t) mempool.GetTotalTxSize(), 1.0f); - statsClient.gauge("transactions.mempool.memoryUsageBytes", (int64_t) mempool.DynamicMemoryUsage(), 1.0f); - statsClient.gauge("transactions.mempool.minFeePerKb", mempool.GetMinFee(args.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000).GetFeePerK(), 1.0f); + ::statsClient->gauge("transactions.mempool.totalTransactions", mempool.size(), 1.0f); + ::statsClient->gauge("transactions.mempool.totalTxBytes", (int64_t) mempool.GetTotalTxSize(), 1.0f); + ::statsClient->gauge("transactions.mempool.memoryUsageBytes", (int64_t) mempool.DynamicMemoryUsage(), 1.0f); + ::statsClient->gauge("transactions.mempool.minFeePerKb", mempool.GetMinFee(args.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000).GetFeePerK(), 1.0f); } } @@ -1524,6 +1525,11 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) fDiscover = args.GetBoolArg("-discover", true); const bool ignores_incoming_txs{args.GetBoolArg("-blocksonly", DEFAULT_BLOCKSONLY)}; + // We need to initialize statsClient early as currently, statsClient is called + // regardless of whether transmitting stats are desirable or not and if + // statsClient isn't present when that attempt is made, the client will crash. + ::statsClient = std::make_unique(); + { // Read asmap file if configured diff --git a/src/net.cpp b/src/net.cpp index 4fcbbfb3c1..a9d06db3d6 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -623,7 +623,7 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo /*inbound_onion=*/false, std::move(i2p_transient_session)); pnode->AddRef(); - statsClient.inc("peers.connect", 1.0f); + ::statsClient->inc("peers.connect", 1.0f); // We're making a new connection, harvest entropy from the time (and our peer count) RandAddEvent((uint32_t)id); @@ -666,7 +666,7 @@ void CNode::CloseSocketDisconnect(CConnman* connman) m_sock.reset(); m_i2p_sam_session.reset(); - statsClient.inc("peers.disconnect", 1.0f); + ::statsClient->inc("peers.disconnect", 1.0f); } void CConnman::AddWhitelistPermissionFlags(NetPermissionFlags& flags, const CNetAddr &addr) const { @@ -817,7 +817,7 @@ bool CNode::ReceiveMsgBytes(Span msg_bytes, bool& complete) } assert(i != mapRecvBytesPerMsgType.end()); i->second += msg.m_raw_message_size; - statsClient.count("bandwidth.message." + std::string(msg.m_type) + ".bytesReceived", msg.m_raw_message_size, 1.0f); + ::statsClient->count("bandwidth.message." + std::string(msg.m_type) + ".bytesReceived", msg.m_raw_message_size, 1.0f); // push the message to the process queue, vRecvMsg.push_back(std::move(msg)); @@ -1741,20 +1741,20 @@ void CConnman::CalculateNumConnectionsChangedStats() torNodes++; const auto last_ping_time = count_microseconds(pnode->m_last_ping_time); if (last_ping_time > 0) - statsClient.timing("peers.ping_us", last_ping_time, 1.0f); + ::statsClient->timing("peers.ping_us", last_ping_time, 1.0f); } for (const std::string &msg : getAllNetMessageTypes()) { - statsClient.gauge("bandwidth.message." + msg + ".totalBytesReceived", mapRecvBytesMsgStats[msg], 1.0f); - statsClient.gauge("bandwidth.message." + msg + ".totalBytesSent", mapSentBytesMsgStats[msg], 1.0f); + ::statsClient->gauge("bandwidth.message." + msg + ".totalBytesReceived", mapRecvBytesMsgStats[msg], 1.0f); + ::statsClient->gauge("bandwidth.message." + msg + ".totalBytesSent", mapSentBytesMsgStats[msg], 1.0f); } - statsClient.gauge("peers.totalConnections", nPrevNodeCount, 1.0f); - statsClient.gauge("peers.spvNodeConnections", spvNodes, 1.0f); - statsClient.gauge("peers.fullNodeConnections", fullNodes, 1.0f); - statsClient.gauge("peers.inboundConnections", inboundNodes, 1.0f); - statsClient.gauge("peers.outboundConnections", outboundNodes, 1.0f); - statsClient.gauge("peers.ipv4Connections", ipv4Nodes, 1.0f); - statsClient.gauge("peers.ipv6Connections", ipv6Nodes, 1.0f); - statsClient.gauge("peers.torConnections", torNodes, 1.0f); + ::statsClient->gauge("peers.totalConnections", nPrevNodeCount, 1.0f); + ::statsClient->gauge("peers.spvNodeConnections", spvNodes, 1.0f); + ::statsClient->gauge("peers.fullNodeConnections", fullNodes, 1.0f); + ::statsClient->gauge("peers.inboundConnections", inboundNodes, 1.0f); + ::statsClient->gauge("peers.outboundConnections", outboundNodes, 1.0f); + ::statsClient->gauge("peers.ipv4Connections", ipv4Nodes, 1.0f); + ::statsClient->gauge("peers.ipv6Connections", ipv6Nodes, 1.0f); + ::statsClient->gauge("peers.torConnections", torNodes, 1.0f); } bool CConnman::ShouldRunInactivityChecks(const CNode& node, std::chrono::seconds now) const @@ -4124,8 +4124,8 @@ bool CConnman::DisconnectNode(NodeId id) void CConnman::RecordBytesRecv(uint64_t bytes) { nTotalBytesRecv += bytes; - statsClient.count("bandwidth.bytesReceived", bytes, 0.1f); - statsClient.gauge("bandwidth.totalBytesReceived", nTotalBytesRecv, 0.01f); + ::statsClient->count("bandwidth.bytesReceived", bytes, 0.1f); + ::statsClient->gauge("bandwidth.totalBytesReceived", nTotalBytesRecv, 0.01f); } void CConnman::RecordBytesSent(uint64_t bytes) @@ -4134,8 +4134,8 @@ void CConnman::RecordBytesSent(uint64_t bytes) LOCK(m_total_bytes_sent_mutex); nTotalBytesSent += bytes; - statsClient.count("bandwidth.bytesSent", bytes, 0.01f); - statsClient.gauge("bandwidth.totalBytesSent", nTotalBytesSent, 0.01f); + ::statsClient->count("bandwidth.bytesSent", bytes, 0.01f); + ::statsClient->gauge("bandwidth.totalBytesSent", nTotalBytesSent, 0.01f); const auto now = GetTime(); if (nMaxOutboundCycleStartTime + MAX_UPLOAD_TIMEFRAME < now) @@ -4291,8 +4291,8 @@ void CConnman::PushMessage(CNode* pnode, CSerializedNetMsg&& msg) msg.data.data() ); - statsClient.count(strprintf("bandwidth.message.%s.bytesSent", msg.m_type), nMessageSize, 1.0f); - statsClient.inc(strprintf("message.sent.%s", msg.m_type), 1.0f); + ::statsClient->count(strprintf("bandwidth.message.%s.bytesSent", msg.m_type), nMessageSize, 1.0f); + ::statsClient->inc(strprintf("message.sent.%s", msg.m_type), 1.0f); { LOCK(pnode->cs_vSend); diff --git a/src/net_processing.cpp b/src/net_processing.cpp index 4c9cb376da..ae060bdaa8 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -1688,9 +1688,9 @@ void PeerManagerImpl::Misbehaving(const NodeId pnode, const int howmuch, const s if (score_now >= DISCOURAGEMENT_THRESHOLD && score_before < DISCOURAGEMENT_THRESHOLD) { warning = " DISCOURAGE THRESHOLD EXCEEDED"; peer->m_should_discourage = true; - statsClient.inc("misbehavior.banned", 1.0f); + ::statsClient->inc("misbehavior.banned", 1.0f); } else { - statsClient.count("misbehavior.amount", howmuch, 1.0); + ::statsClient->count("misbehavior.amount", howmuch, 1.0); } LogPrint(BCLog::NET, "Misbehaving: peer=%d (%d -> %d)%s%s\n", @@ -3260,7 +3260,7 @@ void PeerManagerImpl::ProcessMessage( AssertLockHeld(g_msgproc_mutex); LogPrint(BCLog::NET, "received: %s (%u bytes) peer=%d\n", SanitizeString(msg_type), vRecv.size(), pfrom.GetId()); - statsClient.inc("message.received." + SanitizeString(msg_type), 1.0f); + ::statsClient->inc("message.received." + SanitizeString(msg_type), 1.0f); const bool is_masternode = m_mn_activeman != nullptr; @@ -3759,7 +3759,7 @@ void PeerManagerImpl::ProcessMessage( if (inv.IsMsgBlk()) { const bool fAlreadyHave = AlreadyHaveBlock(inv.hash); LogPrint(BCLog::NET, "got inv: %s %s peer=%d\n", inv.ToString(), fAlreadyHave ? "have" : "new", pfrom.GetId()); - statsClient.inc(strprintf("message.received.inv_%s", inv.GetCommand()), 1.0f); + ::statsClient->inc(strprintf("message.received.inv_%s", inv.GetCommand()), 1.0f); UpdateBlockAvailability(pfrom.GetId(), inv.hash); if (!fAlreadyHave && !fImporting && !fReindex && !mapBlocksInFlight.count(inv.hash)) { @@ -3774,7 +3774,7 @@ void PeerManagerImpl::ProcessMessage( } else { const bool fAlreadyHave = AlreadyHave(inv); LogPrint(BCLog::NET, "got inv: %s %s peer=%d\n", inv.ToString(), fAlreadyHave ? "have" : "new", pfrom.GetId()); - statsClient.inc(strprintf("message.received.inv_%s", inv.GetCommand()), 1.0f); + ::statsClient->inc(strprintf("message.received.inv_%s", inv.GetCommand()), 1.0f); static std::set allowWhileInIBDObjs = { MSG_SPORK diff --git a/src/statsd_client.cpp b/src/statsd_client.cpp index d291510ac6..4fc9170245 100644 --- a/src/statsd_client.cpp +++ b/src/statsd_client.cpp @@ -38,7 +38,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -statsd::StatsdClient statsClient; +std::unique_ptr statsClient; namespace statsd { diff --git a/src/statsd_client.h b/src/statsd_client.h index f06fd1b5c1..5b6dea5799 100644 --- a/src/statsd_client.h +++ b/src/statsd_client.h @@ -66,6 +66,6 @@ class StatsdClient { } // namespace statsd -extern statsd::StatsdClient statsClient; +extern std::unique_ptr statsClient; #endif // BITCOIN_STATSD_CLIENT_H diff --git a/src/test/util/setup_common.cpp b/src/test/util/setup_common.cpp index 7f775a14e7..ac4b868ed5 100644 --- a/src/test/util/setup_common.cpp +++ b/src/test/util/setup_common.cpp @@ -39,6 +39,7 @@ #include #include