Files
Towards/modules/network/include/metrics/NetworkStatsLogger.hpp
T
Martin Slachta a04f0dc262 initial
2026-07-18 14:31:15 +02:00

135 lines
3.5 KiB
C++

#pragma once
#include <cstdint>
#include <chrono>
#include <filesystem>
#include <cassert>
#include "Address.hpp"
#include "BucketMetric.hpp"
#include "packets/Packet.hpp"
#include "MessageRegistry.hpp"
namespace tw::net {
using Clock = std::chrono::steady_clock;
using TimePoint = Clock::time_point;
struct NetworkSendInfo {
PacketType message_type;
bool is_sent_by_us;
Address target;
TimePoint timepoint;
std::span<uint8_t> buffer;
NetworkSendInfo(
PacketType message_type,
bool is_sent_by_us,
const Address& target,
const std::span<uint8_t> buffer
) :
message_type(message_type),
is_sent_by_us(is_sent_by_us),
target(target),
timepoint(std::chrono::steady_clock::now()),
buffer(buffer)
{
}
};
class NetworkStatsLogger {
private:
std::vector<NetworkSendInfo> m_backlog;
std::vector<uint8_t> m_buffer;
size_t m_left, m_right;
std::optional<std::ostream> m_output;
using Interval = std::chrono::seconds;
BucketMetric<uint32_t, Interval, AverageOp<uint32_t>> m_ping_metric;
BucketMetric<uint32_t, Interval, SumOp<uint32_t>> m_outgoing;
BucketMetric<uint32_t, Interval, SumOp<uint32_t>> m_incoming;
public:
NetworkStatsLogger() :
m_backlog(10000, {MESSAGE_PACKET, false, Address({}, 0), {}}),
m_buffer(1000000),
m_left(0), m_right(0),
m_ping_metric("ms", 1000),
m_outgoing("b/s", 1000),
m_incoming("b/s", 1000)
{ }
void set_file_output(std::filesystem::path path);
size_t get_size() {
return m_right - m_left + (m_right < m_left ? m_backlog.size() : 0);
}
NetworkSendInfo& get_item(uint32_t idx) {
return m_backlog[(m_left + idx) % m_backlog.size()];
}
std::span<uint8_t> allocate_memory_for_buffer(size_t size) {
uint32_t start = m_right;
if(m_buffer.size() - m_right < size) {
// throw away packets from the start to make space
for(; m_backlog[m_left].buffer.data() < m_buffer.data() + start + size &&
m_left != m_right; m_left = (m_left + 1) % m_buffer.size()) { }
start = 0;
}
uint32_t end = start + size;
return std::span<uint8_t>(m_buffer.begin() + start, m_buffer.begin() + end);
}
// constexpr void log(PacketType message_type, bool is_sent, const Address& target, const ByteBuffer& content) {
// std::span<uint8_t> span = allocate_memory_for_buffer(content.size());
// memcpy(span.data(), content.data().data(), content.size());
// m_right = (m_right + 1) % m_backlog.size();
// m_backlog[m_right] = NetworkSendInfo(message_type, is_sent, target, span);
// }
// constexpr void log_receive(
// PacketType message_type,
// const Address& from
// ) {
// log(message_type, false, from, content);
// m_incoming.push(content.size());
// }
// constexpr void log_send(
// PacketType message_type,
// const Address& to
// ) {
// log(message_type, true, to, content);
// m_outgoing.push(content.size());
// }
void log_ping(uint32_t ping) {
m_ping_metric.push(ping);
}
BucketMetric<uint32_t, Interval, AverageOp<uint32_t>>& ping(){
return m_ping_metric;
}
BucketMetric<uint32_t, Interval>& outgoing(){
return m_outgoing;
}
BucketMetric<uint32_t, Interval>& incoming(){
return m_incoming;
}
};
}