diff --git a/llarp/peerstats/peer_db.cpp b/llarp/peerstats/peer_db.cpp index 9f1966ce8..220953123 100644 --- a/llarp/peerstats/peer_db.cpp +++ b/llarp/peerstats/peer_db.cpp @@ -1,6 +1,7 @@ #include #include +#include #include namespace llarp @@ -80,7 +81,7 @@ namespace llarp auto end = time_now_ms(); auto elapsed = end - start; - LogDebug("PeerDb flush took about ", elapsed, " millis"); + LogInfo("PeerDb flush took about ", elapsed, " millis"); m_lastFlush.store(end); } @@ -128,19 +129,24 @@ namespace llarp RouterID id(rc.pubkey); auto& stats = m_peerStats[id]; + stats.routerId = id.ToString(); if (stats.lastRCUpdated < rc.last_updated.count()) { - // we track max expiry as the delta between (time received - last expiration time), - // and this value will often be negative for a healthy router - // TODO: handle case where new RC is also expired? just ignore? - int64_t expiry = (now.count() - (stats.lastRCUpdated + RouterContact::Lifetime.count())); - - if (stats.numDistinctRCsReceived == 0) - stats.mostExpiredRCMs = expiry; - else + if (stats.numDistinctRCsReceived > 0) + { + // we track max expiry as the delta between (time received - last expiration time), + // and this value will often be negative for a healthy router + // TODO: handle case where new RC is also expired? just ignore? + int64_t expiry = (now.count() - (stats.lastRCUpdated + RouterContact::Lifetime.count())); stats.mostExpiredRCMs = std::max(stats.mostExpiredRCMs, expiry); + if (stats.numDistinctRCsReceived == 1) + stats.mostExpiredRCMs = expiry; + else + stats.mostExpiredRCMs = std::max(stats.mostExpiredRCMs, expiry); + } + stats.numDistinctRCsReceived++; stats.lastRCUpdated = rc.last_updated.count(); } @@ -164,4 +170,32 @@ namespace llarp return (now - m_lastFlush.load() >= TargetFlushInterval); } + util::StatusObject + PeerDb::ExtractStatus() const + { + std::lock_guard gaurd(m_statsLock); + + bool loaded = (m_storage.get() != nullptr); + util::StatusObject dbFile = nullptr; + if (loaded) + dbFile = m_storage->filename(); + + std::vector statsObjs; + statsObjs.reserve(m_peerStats.size()); + LogInfo("Building peer stats..."); + for (const auto& pair : m_peerStats) + { + LogInfo("Stat here"); + statsObjs.push_back(pair.second.toJson()); + } + + util::StatusObject obj{ + {"dbLoaded", loaded}, + {"dbFile", dbFile}, + {"lastFlushMs", m_lastFlush.load().count()}, + {"stats", statsObjs}, + }; + return obj; + } + }; // namespace llarp diff --git a/llarp/peerstats/peer_db.hpp b/llarp/peerstats/peer_db.hpp index 3280447ce..6f0c2e98f 100644 --- a/llarp/peerstats/peer_db.hpp +++ b/llarp/peerstats/peer_db.hpp @@ -104,6 +104,12 @@ namespace llarp bool shouldFlush(llarp_time_t now); + /// Get JSON status for API + /// + /// @return JSON object representing our current status + util::StatusObject + ExtractStatus() const; + private: std::unordered_map m_peerStats; std::mutex m_statsLock; diff --git a/llarp/peerstats/types.cpp b/llarp/peerstats/types.cpp index bcb36573e..f3cd5368c 100644 --- a/llarp/peerstats/types.cpp +++ b/llarp/peerstats/types.cpp @@ -30,6 +30,7 @@ namespace llarp longestRCReceiveIntervalMs = std::max(longestRCReceiveIntervalMs, other.longestRCReceiveIntervalMs); mostExpiredRCMs = std::max(mostExpiredRCMs, other.mostExpiredRCMs); + lastRCUpdated = std::max(lastRCUpdated, other.lastRCUpdated); return *this; } @@ -52,7 +53,30 @@ namespace llarp and peakBandwidthBytesPerSec == other.peakBandwidthBytesPerSec and longestRCReceiveIntervalMs == other.longestRCReceiveIntervalMs - and mostExpiredRCMs == other.mostExpiredRCMs; + and mostExpiredRCMs == other.mostExpiredRCMs and lastRCUpdated == other.lastRCUpdated; + } + + util::StatusObject + PeerStats::toJson() const + { + return { + {"routerId", routerId}, + // {"numConnectionAttempts", numConnectionAttempts}, + // {"numConnectionSuccesses", numConnectionSuccesses}, + // {"numConnectionRejections", numConnectionRejections}, + // {"numConnectionTimeouts", numConnectionTimeouts}, + // {"numPathBuilds", numPathBuilds}, + // {"numPacketsAttempted", numPacketsAttempted}, + // {"numPacketsSent", numPacketsSent}, + // {"numPacketsDropped", numPacketsDropped}, + // {"numPacketsResent", numPacketsResent}, + {"numDistinctRCsReceived", numDistinctRCsReceived}, + {"numLateRCs", numLateRCs}, + // {"peakBandwidthBytesPerSec", peakBandwidthBytesPerSec}, + {"longestRCReceiveIntervalMs", longestRCReceiveIntervalMs}, + {"mostExpiredRCMs", mostExpiredRCMs}, + {"lastRCUpdated", lastRCUpdated}, + }; } }; // namespace llarp diff --git a/llarp/peerstats/types.hpp b/llarp/peerstats/types.hpp index ffab7afdc..7db98a40d 100644 --- a/llarp/peerstats/types.hpp +++ b/llarp/peerstats/types.hpp @@ -4,6 +4,7 @@ #include #include +#include #include /// Types stored in our peerstats database are declared here @@ -41,6 +42,9 @@ namespace llarp operator+=(const PeerStats& other); bool operator==(const PeerStats& other); + + util::StatusObject + toJson() const; }; } // namespace llarp diff --git a/llarp/router/router.cpp b/llarp/router/router.cpp index 1b040d7c1..0dea08ae7 100644 --- a/llarp/router/router.cpp +++ b/llarp/router/router.cpp @@ -23,6 +23,7 @@ #include #include "tooling/router_event.hpp" +#include "util/status.hpp" #include #include @@ -80,13 +81,19 @@ namespace llarp { if (_running) { - return util::StatusObject{{"running", true}, - {"numNodesKnown", _nodedb->num_loaded()}, - {"dht", _dht->impl->ExtractStatus()}, - {"services", _hiddenServiceContext.ExtractStatus()}, - {"exit", _exitContext.ExtractStatus()}, - {"links", _linkManager.ExtractStatus()}, - {"outboundMessages", _outboundMessageHandler.ExtractStatus()}}; + util::StatusObject peerStatsObj = nullptr; + if (m_peerDb) + peerStatsObj = m_peerDb->ExtractStatus(); + + return util::StatusObject{ + {"running", true}, + {"numNodesKnown", _nodedb->num_loaded()}, + {"dht", _dht->impl->ExtractStatus()}, + {"services", _hiddenServiceContext.ExtractStatus()}, + {"exit", _exitContext.ExtractStatus()}, + {"links", _linkManager.ExtractStatus()}, + {"outboundMessages", _outboundMessageHandler.ExtractStatus()}, + {"peerStats", peerStatsObj}}; } else { diff --git a/test/peerstats/test_peer_db.cpp b/test/peerstats/test_peer_db.cpp index bab8c5cbb..d6d2f5918 100644 --- a/test/peerstats/test_peer_db.cpp +++ b/test/peerstats/test_peer_db.cpp @@ -130,7 +130,7 @@ TEST_CASE("Test PeerDb handleGossipedRC", "[PeerDb]") auto stats = db.getCurrentPeerStats(id); CHECK(stats.has_value()); - CHECK(stats.value().mostExpiredRCMs == (0s - rcLifetime).count()); + CHECK(stats.value().mostExpiredRCMs == 0); // not calculated on first received RC CHECK(stats.value().numDistinctRCsReceived == 1); CHECK(stats.value().lastRCUpdated == 10000); @@ -139,7 +139,7 @@ TEST_CASE("Test PeerDb handleGossipedRC", "[PeerDb]") stats = db.getCurrentPeerStats(id); CHECK(stats.has_value()); // these values should remain unchanged, this is not a new RC - CHECK(stats.value().mostExpiredRCMs == (0s - rcLifetime).count()); + CHECK(stats.value().mostExpiredRCMs == 0); CHECK(stats.value().numDistinctRCsReceived == 1); CHECK(stats.value().lastRCUpdated == 10000);