Add API query for peer stats, other related fixes

pull/1312/head
Stephen Shelton 4 years ago
parent 595288e046
commit 5e05defc76
No known key found for this signature in database
GPG Key ID: EE4BADACCE8B631C

@ -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…
Cancel
Save