Skip to main content

rs_netty/context/
stats.rs

1use std::{
2    sync::{
3        atomic::{AtomicU64, Ordering},
4        Arc,
5    },
6    time::Instant,
7};
8
9/// Snapshot handle for per-connection counters.
10///
11/// Frame counters are updated when frames are decoded or encoded. With manual
12/// flush semantics, `frames_written` can increase before `bytes_written`
13/// because encoded frames may remain buffered until `flush` or
14/// `write_and_flush` sends them.
15///
16/// Cloning this handle is cheap. Counter reads use relaxed atomics and are
17/// intended for monitoring, not synchronization.
18#[derive(Clone)]
19pub struct ConnectionStats {
20    inner: Arc<ConnectionStatsInner>,
21}
22
23struct ConnectionStatsInner {
24    connected_at: Instant,
25    bytes_read: AtomicU64,
26    bytes_written: AtomicU64,
27    frames_read: AtomicU64,
28    frames_written: AtomicU64,
29}
30
31impl ConnectionStats {
32    pub(crate) fn new() -> Self {
33        Self {
34            inner: Arc::new(ConnectionStatsInner {
35                connected_at: Instant::now(),
36                bytes_read: AtomicU64::new(0),
37                bytes_written: AtomicU64::new(0),
38                frames_read: AtomicU64::new(0),
39                frames_written: AtomicU64::new(0),
40            }),
41        }
42    }
43
44    /// Instant when the connection stats were created.
45    pub fn connected_at(&self) -> Instant {
46        self.inner.connected_at
47    }
48
49    /// Total bytes read from the socket.
50    pub fn bytes_read(&self) -> u64 {
51        self.inner.bytes_read.load(Ordering::Relaxed)
52    }
53
54    /// Total bytes written to the socket.
55    pub fn bytes_written(&self) -> u64 {
56        self.inner.bytes_written.load(Ordering::Relaxed)
57    }
58
59    /// Total decoded frames.
60    pub fn frames_read(&self) -> u64 {
61        self.inner.frames_read.load(Ordering::Relaxed)
62    }
63
64    /// Total encoded frames.
65    ///
66    /// This counts frames encoded into the write buffer, not necessarily frames
67    /// already flushed to the socket.
68    pub fn frames_written(&self) -> u64 {
69        self.inner.frames_written.load(Ordering::Relaxed)
70    }
71
72    pub(crate) fn add_bytes_read(&self, value: usize) {
73        self.inner
74            .bytes_read
75            .fetch_add(value as u64, Ordering::Relaxed);
76    }
77
78    pub(crate) fn add_bytes_written(&self, value: usize) {
79        self.inner
80            .bytes_written
81            .fetch_add(value as u64, Ordering::Relaxed);
82    }
83
84    pub(crate) fn add_frame_read(&self) {
85        self.inner.frames_read.fetch_add(1, Ordering::Relaxed);
86    }
87
88    pub(crate) fn add_frame_written(&self) {
89        self.inner.frames_written.fetch_add(1, Ordering::Relaxed);
90    }
91}