Skip to main content

fips_core/transport/ble/
stats.rs

1//! BLE transport statistics.
2
3use portable_atomic::{AtomicU64, Ordering};
4
5use serde::Serialize;
6
7/// Statistics for a BLE transport instance.
8///
9/// Uses atomic counters for lock-free updates from per-connection
10/// receive loops and the send path concurrently.
11#[derive(Default)]
12pub struct BleStats {
13    pub packets_sent: AtomicU64,
14    pub bytes_sent: AtomicU64,
15    pub packets_recv: AtomicU64,
16    pub bytes_recv: AtomicU64,
17    pub send_errors: AtomicU64,
18    pub recv_errors: AtomicU64,
19    pub mtu_exceeded: AtomicU64,
20    pub connections_established: AtomicU64,
21    pub connections_accepted: AtomicU64,
22    pub connections_rejected: AtomicU64,
23    pub connect_timeouts: AtomicU64,
24    pub pool_evictions: AtomicU64,
25    pub advertisements_sent: AtomicU64,
26    pub scan_results: AtomicU64,
27}
28
29impl BleStats {
30    /// Create a new stats instance with all counters at zero.
31    pub fn new() -> Self {
32        Self::default()
33    }
34
35    /// Record a successful send.
36    pub fn record_send(&self, bytes: usize) {
37        self.packets_sent.fetch_add(1, Ordering::Relaxed);
38        self.bytes_sent.fetch_add(bytes as u64, Ordering::Relaxed);
39    }
40
41    /// Record a successful receive.
42    pub fn record_recv(&self, bytes: usize) {
43        self.packets_recv.fetch_add(1, Ordering::Relaxed);
44        self.bytes_recv.fetch_add(bytes as u64, Ordering::Relaxed);
45    }
46
47    /// Record a send error.
48    pub fn record_send_error(&self) {
49        self.send_errors.fetch_add(1, Ordering::Relaxed);
50    }
51
52    /// Record a receive error.
53    pub fn record_recv_error(&self) {
54        self.recv_errors.fetch_add(1, Ordering::Relaxed);
55    }
56
57    /// Record an MTU exceeded rejection.
58    pub fn record_mtu_exceeded(&self) {
59        self.mtu_exceeded.fetch_add(1, Ordering::Relaxed);
60    }
61
62    /// Record a successful outbound connection.
63    pub fn record_connection_established(&self) {
64        self.connections_established.fetch_add(1, Ordering::Relaxed);
65    }
66
67    /// Record a successful inbound connection.
68    pub fn record_connection_accepted(&self) {
69        self.connections_accepted.fetch_add(1, Ordering::Relaxed);
70    }
71
72    /// Record a rejected inbound connection (pool full).
73    pub fn record_connection_rejected(&self) {
74        self.connections_rejected.fetch_add(1, Ordering::Relaxed);
75    }
76
77    /// Record a connect timeout.
78    pub fn record_connect_timeout(&self) {
79        self.connect_timeouts.fetch_add(1, Ordering::Relaxed);
80    }
81
82    /// Record a pool eviction (non-static peer displaced).
83    pub fn record_pool_eviction(&self) {
84        self.pool_evictions.fetch_add(1, Ordering::Relaxed);
85    }
86
87    /// Record an advertisement broadcast.
88    pub fn record_advertisement(&self) {
89        self.advertisements_sent.fetch_add(1, Ordering::Relaxed);
90    }
91
92    /// Record a scan result received.
93    pub fn record_scan_result(&self) {
94        self.scan_results.fetch_add(1, Ordering::Relaxed);
95    }
96
97    /// Take a snapshot of all counters.
98    pub fn snapshot(&self) -> BleStatsSnapshot {
99        BleStatsSnapshot {
100            packets_sent: self.packets_sent.load(Ordering::Relaxed),
101            bytes_sent: self.bytes_sent.load(Ordering::Relaxed),
102            packets_recv: self.packets_recv.load(Ordering::Relaxed),
103            bytes_recv: self.bytes_recv.load(Ordering::Relaxed),
104            send_errors: self.send_errors.load(Ordering::Relaxed),
105            recv_errors: self.recv_errors.load(Ordering::Relaxed),
106            mtu_exceeded: self.mtu_exceeded.load(Ordering::Relaxed),
107            connections_established: self.connections_established.load(Ordering::Relaxed),
108            connections_accepted: self.connections_accepted.load(Ordering::Relaxed),
109            connections_rejected: self.connections_rejected.load(Ordering::Relaxed),
110            connect_timeouts: self.connect_timeouts.load(Ordering::Relaxed),
111            pool_evictions: self.pool_evictions.load(Ordering::Relaxed),
112            advertisements_sent: self.advertisements_sent.load(Ordering::Relaxed),
113            scan_results: self.scan_results.load(Ordering::Relaxed),
114        }
115    }
116}
117
118/// Point-in-time snapshot of BLE stats (non-atomic, copyable).
119#[derive(Clone, Debug, Default, Serialize)]
120pub struct BleStatsSnapshot {
121    pub packets_sent: u64,
122    pub bytes_sent: u64,
123    pub packets_recv: u64,
124    pub bytes_recv: u64,
125    pub send_errors: u64,
126    pub recv_errors: u64,
127    pub mtu_exceeded: u64,
128    pub connections_established: u64,
129    pub connections_accepted: u64,
130    pub connections_rejected: u64,
131    pub connect_timeouts: u64,
132    pub pool_evictions: u64,
133    pub advertisements_sent: u64,
134    pub scan_results: u64,
135}