mirror of https://github.com/oxen-io/lokinet
Begin peer stats infrastructure
parent
352cc12780
commit
73c9ddff52
@ -0,0 +1 @@
|
||||
Subproject commit f7ef17a6bde6162e8b487deb36519bace412920a
|
@ -0,0 +1,67 @@
|
||||
#include <peerstats/peer_db.hpp>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
PeerStats&
|
||||
PeerStats::operator+=(const PeerStats& other)
|
||||
{
|
||||
numConnectionAttempts += other.numConnectionAttempts;
|
||||
numConnectionSuccesses += other.numConnectionSuccesses;
|
||||
numConnectionRejections += other.numConnectionRejections;
|
||||
numConnectionTimeouts += other.numConnectionTimeouts;
|
||||
|
||||
numPathBuilds += other.numPathBuilds;
|
||||
numPacketsAttempted += other.numPacketsAttempted;
|
||||
numPacketsSent += other.numPacketsSent;
|
||||
numPacketsDropped += other.numPacketsDropped;
|
||||
numPacketsResent += other.numPacketsResent;
|
||||
|
||||
numDistinctRCsReceived += other.numDistinctRCsReceived;
|
||||
numLateRCs += other.numLateRCs;
|
||||
|
||||
peakBandwidthBytesPerSec = std::max(peakBandwidthBytesPerSec, other.peakBandwidthBytesPerSec);
|
||||
longestRCReceiveInterval = std::max(longestRCReceiveInterval, other.longestRCReceiveInterval);
|
||||
mostExpiredRC = std::max(mostExpiredRC, other.mostExpiredRC);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool
|
||||
PeerStats::operator==(const PeerStats& other)
|
||||
{
|
||||
return numConnectionAttempts == other.numConnectionAttempts
|
||||
and numConnectionSuccesses == other.numConnectionSuccesses
|
||||
and numConnectionRejections == other.numConnectionRejections
|
||||
and numConnectionTimeouts == other.numConnectionTimeouts
|
||||
|
||||
and numPathBuilds == other.numPathBuilds
|
||||
and numPacketsAttempted == other.numPacketsAttempted
|
||||
and numPacketsSent == other.numPacketsSent and numPacketsDropped == other.numPacketsDropped
|
||||
and numPacketsResent == other.numPacketsResent
|
||||
|
||||
and numDistinctRCsReceived == other.numDistinctRCsReceived
|
||||
and numLateRCs == other.numLateRCs
|
||||
|
||||
and peakBandwidthBytesPerSec == peakBandwidthBytesPerSec
|
||||
and longestRCReceiveInterval == longestRCReceiveInterval and mostExpiredRC == mostExpiredRC;
|
||||
}
|
||||
|
||||
void
|
||||
PeerDb::accumulatePeerStats(const RouterID& routerId, const PeerStats& delta)
|
||||
{
|
||||
std::lock_guard gaurd(m_statsLock);
|
||||
m_peerStats[routerId] += delta;
|
||||
}
|
||||
|
||||
PeerStats
|
||||
PeerDb::getCurrentPeerStats(const RouterID& routerId) const
|
||||
{
|
||||
std::lock_guard gaurd(m_statsLock);
|
||||
auto itr = m_peerStats.find(routerId);
|
||||
if (itr == m_peerStats.end())
|
||||
return {};
|
||||
else
|
||||
return itr->second;
|
||||
}
|
||||
|
||||
}; // namespace llarp
|
@ -0,0 +1,69 @@
|
||||
#pragma once
|
||||
|
||||
#include <chrono>
|
||||
#include <unordered_map>
|
||||
|
||||
#include <sqlite_orm/sqlite_orm.h>
|
||||
|
||||
#include <router_id.hpp>
|
||||
#include <util/time.hpp>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
// Struct containing stats we know about a peer
|
||||
struct PeerStats
|
||||
{
|
||||
int32_t numConnectionAttempts = 0;
|
||||
int32_t numConnectionSuccesses = 0;
|
||||
int32_t numConnectionRejections = 0;
|
||||
int32_t numConnectionTimeouts = 0;
|
||||
|
||||
int32_t numPathBuilds = 0;
|
||||
int64_t numPacketsAttempted = 0;
|
||||
int64_t numPacketsSent = 0;
|
||||
int64_t numPacketsDropped = 0;
|
||||
int64_t numPacketsResent = 0;
|
||||
|
||||
int64_t numDistinctRCsReceived = 0;
|
||||
int64_t numLateRCs = 0;
|
||||
|
||||
double peakBandwidthBytesPerSec = 0;
|
||||
std::chrono::milliseconds longestRCReceiveInterval = 0ms;
|
||||
std::chrono::milliseconds mostExpiredRC = 0ms;
|
||||
|
||||
PeerStats&
|
||||
operator+=(const PeerStats& other);
|
||||
bool
|
||||
operator==(const PeerStats& other);
|
||||
};
|
||||
|
||||
/// Maintains a database of stats collected about the connections with our Service Node peers
|
||||
struct PeerDb
|
||||
{
|
||||
/// Add the given stats to the cummulative stats for the given peer. For cummulative stats, the
|
||||
/// stats are added together; for watermark stats, the max is kept.
|
||||
///
|
||||
/// This is intended to be used in the following pattern:
|
||||
///
|
||||
/// 1) Initialize an empty PeerStats
|
||||
/// 2) Collect relevant stats
|
||||
/// 3) Call accumulatePeerStats() with the stats
|
||||
/// 4) Reset the stats to 0
|
||||
/// 5) <Repeat 2-4 periodically>
|
||||
void
|
||||
accumulatePeerStats(const RouterID& routerId, const PeerStats& delta);
|
||||
|
||||
/// Provides a snapshot of the most recent PeerStats we have for the given peer. If we don't
|
||||
/// have any stats for the peer, an empty PeerStats is returned.
|
||||
///
|
||||
/// @param routerId is the RouterID of the requested peer
|
||||
/// @return a copy of the most recent peer stats or an empty one if no such peer is known
|
||||
PeerStats
|
||||
getCurrentPeerStats(const RouterID& routerId) const;
|
||||
|
||||
private:
|
||||
std::unordered_map<RouterID, PeerStats, RouterID::Hash> m_peerStats;
|
||||
std::mutex m_statsLock;
|
||||
};
|
||||
|
||||
} // namespace llarp
|
@ -0,0 +1,46 @@
|
||||
#include <numeric>
|
||||
#include <peerstats/peer_db.hpp>
|
||||
|
||||
#include <catch2/catch.hpp>
|
||||
|
||||
TEST_CASE("Test PeerStats operator+=", "[PeerStats]")
|
||||
{
|
||||
// TODO: test all members
|
||||
llarp::PeerStats stats;
|
||||
stats.numConnectionAttempts = 1;
|
||||
stats.peakBandwidthBytesPerSec = 12;
|
||||
|
||||
llarp::PeerStats delta;
|
||||
delta.numConnectionAttempts = 2;
|
||||
delta.peakBandwidthBytesPerSec = 4;
|
||||
|
||||
stats += delta;
|
||||
|
||||
CHECK(stats.numConnectionAttempts == 3);
|
||||
CHECK(stats.peakBandwidthBytesPerSec == 12); // should take max(), not add
|
||||
}
|
||||
|
||||
TEST_CASE("Test PeerDb PeerStats memory storage", "[PeerDb]")
|
||||
{
|
||||
const llarp::PeerStats empty = {};
|
||||
const llarp::RouterID id = {};
|
||||
|
||||
llarp::PeerDb db;
|
||||
CHECK(db.getCurrentPeerStats(id) == empty);
|
||||
|
||||
llarp::PeerStats delta;
|
||||
delta.numConnectionAttempts = 4;
|
||||
delta.peakBandwidthBytesPerSec = 5;
|
||||
db.accumulatePeerStats(id, delta);
|
||||
CHECK(db.getCurrentPeerStats(id) == delta);
|
||||
|
||||
delta = {};
|
||||
delta.numConnectionAttempts = 5;
|
||||
delta.peakBandwidthBytesPerSec = 6;
|
||||
db.accumulatePeerStats(id, delta);
|
||||
|
||||
llarp::PeerStats expected;
|
||||
expected.numConnectionAttempts = 9;
|
||||
expected.peakBandwidthBytesPerSec = 6;
|
||||
CHECK(db.getCurrentPeerStats(id) == expected);
|
||||
}
|
Loading…
Reference in New Issue