Begin peer stats infrastructure

pull/1312/head
Stephen Shelton 4 years ago
parent 352cc12780
commit 73c9ddff52
No known key found for this signature in database
GPG Key ID: EE4BADACCE8B631C

3
.gitmodules vendored

@ -31,3 +31,6 @@
path = external/loki-mq
url = https://github.com/loki-project/loki-mq
branch = dev
[submodule "external/sqlite_orm"]
path = external/sqlite_orm
url = https://github.com/fnc12/sqlite_orm

@ -305,6 +305,7 @@ if(SUBMODULE_CHECK)
check_submodule(external/ghc-filesystem)
check_submodule(external/date)
check_submodule(external/pybind11)
check_submodule(external/sqlite_orm)
if (NOT WIN32) # we grab libuv for windows separately in win32-setup/libuv. see note in cmake/win32.cmake.
check_submodule(external/libuv)
endif()
@ -324,6 +325,8 @@ add_subdirectory(external/nlohmann EXCLUDE_FROM_ALL)
add_subdirectory(external/cxxopts EXCLUDE_FROM_ALL)
add_subdirectory(external/date EXCLUDE_FROM_ALL)
include_directories(SYSTEM external/sqlite_orm/include)
add_subdirectory(vendor)
if(ANDROID)

@ -0,0 +1 @@
Subproject commit f7ef17a6bde6162e8b487deb36519bace412920a

@ -34,13 +34,13 @@ target_link_libraries(lokinet-util PUBLIC
filesystem
date::date
lokimq
sqlite3
)
if(ANDROID)
target_link_libraries(lokinet-util PUBLIC log)
endif()
add_library(lokinet-platform
# for networking
ev/ev.cpp
@ -156,6 +156,7 @@ add_library(liblokinet
path/pathbuilder.cpp
path/pathset.cpp
path/transit_hop.cpp
peerstats/peer_db.cpp
pow.cpp
profiling.cpp
router/outbound_message_handler.cpp

@ -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

@ -68,6 +68,7 @@ add_executable(catchAll
util/test_llarp_util_printer.cpp
util/test_llarp_util_str.cpp
util/test_llarp_util_decaying_hashset.cpp
peerstats/peer_db.cpp
config/test_llarp_config_definition.cpp
config/test_llarp_config_output.cpp
net/test_ip_address.cpp

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