bitfold_peer/
statistics.rs

1//! Peer connection statistics tracking.
2//!
3//! This module provides comprehensive statistics tracking for peer connections,
4//! including metrics for packets sent/received, bytes transferred, and network
5//! quality indicators like packet loss rate.
6
7/// Comprehensive statistics for a peer connection.
8/// Tracks packets, bytes, and network quality metrics.
9#[derive(Debug, Clone, Default)]
10pub struct PeerStatistics {
11    /// Total packets sent to this peer
12    pub packets_sent: u64,
13    /// Total packets received from this peer
14    pub packets_received: u64,
15    /// Total packets lost (detected via ACK timeouts)
16    pub packets_lost: u64,
17    /// Total data bytes sent to this peer (excluding protocol overhead)
18    pub bytes_sent: u64,
19    /// Total data bytes received from this peer (excluding protocol overhead)
20    pub bytes_received: u64,
21}
22
23impl PeerStatistics {
24    /// Returns the packet loss rate (0.0 to 1.0).
25    pub fn packet_loss_rate(&self) -> f32 {
26        if self.packets_sent == 0 {
27            return 0.0;
28        }
29        self.packets_lost as f32 / self.packets_sent as f32
30    }
31
32    /// Resets all statistics counters.
33    pub fn reset(&mut self) {
34        *self = Self::default();
35    }
36}
37
38#[cfg(test)]
39mod tests {
40    use super::*;
41
42    #[test]
43    fn test_statistics_initialized_to_zero() {
44        let stats = PeerStatistics::default();
45        assert_eq!(stats.packets_sent, 0);
46        assert_eq!(stats.packets_received, 0);
47        assert_eq!(stats.packets_lost, 0);
48        assert_eq!(stats.bytes_sent, 0);
49        assert_eq!(stats.bytes_received, 0);
50        assert_eq!(stats.packet_loss_rate(), 0.0);
51    }
52
53    #[test]
54    fn test_statistics_packet_loss_rate() {
55        let mut stats = PeerStatistics::default();
56        stats.packets_sent = 100;
57        stats.packets_lost = 10;
58
59        let loss_rate = stats.packet_loss_rate();
60        assert!((loss_rate - 0.1).abs() < 0.001); // 10/100 = 0.1 = 10%
61    }
62
63    #[test]
64    fn test_statistics_packet_loss_rate_no_packets_sent() {
65        let stats = PeerStatistics::default();
66        assert_eq!(stats.packet_loss_rate(), 0.0);
67    }
68
69    #[test]
70    fn test_statistics_reset() {
71        let mut stats = PeerStatistics::default();
72        stats.packets_sent = 100;
73        stats.packets_received = 90;
74        stats.packets_lost = 10;
75        stats.bytes_sent = 10000;
76        stats.bytes_received = 9000;
77
78        stats.reset();
79
80        assert_eq!(stats.packets_sent, 0);
81        assert_eq!(stats.packets_received, 0);
82        assert_eq!(stats.packets_lost, 0);
83        assert_eq!(stats.bytes_sent, 0);
84        assert_eq!(stats.bytes_received, 0);
85    }
86
87    #[test]
88    fn test_statistics_track_packet_loss() {
89        let mut stats = PeerStatistics::default();
90        stats.packets_lost = 5;
91        assert_eq!(stats.packets_lost, 5);
92    }
93}