mirror of https://github.com/oxen-io/lokinet
Add API query for peer stats, other related fixes
This commit is contained in:
parent
595288e046
commit
5e05defc76
|
@ -1,6 +1,7 @@
|
|||
#include <peerstats/peer_db.hpp>
|
||||
|
||||
#include <util/logging/logger.hpp>
|
||||
#include <util/status.hpp>
|
||||
#include <util/str.hpp>
|
||||
|
||||
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<util::StatusObject> 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
|
||||
|
|
|
@ -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<RouterID, PeerStats, RouterID::Hash> m_peerStats;
|
||||
std::mutex m_statsLock;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <unordered_map>
|
||||
|
||||
#include <router_id.hpp>
|
||||
#include <util/status.hpp>
|
||||
#include <util/time.hpp>
|
||||
|
||||
/// 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
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include <ev/ev.hpp>
|
||||
|
||||
#include "tooling/router_event.hpp"
|
||||
#include "util/status.hpp"
|
||||
|
||||
#include <fstream>
|
||||
#include <cstdlib>
|
||||
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue