1use metricator::RateMetric;
7use monotonic_time_rs::Millis;
8
9#[cfg(feature = "log")]
10use monotonic_time_rs::MillisDuration;
11
12use std::fmt::Display;
13
14pub struct MetricsInDirection {
15 pub datagrams_per_second: f32,
16 pub octets_per_second: f32,
17}
18
19impl Display for MetricsInDirection {
20 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
21 write!(
22 f,
23 "{} datagrams/s {} octets/s",
24 self.datagrams_per_second, self.octets_per_second
25 )
26 }
27}
28
29pub struct CombinedMetrics {
30 pub outgoing: MetricsInDirection,
31 pub incoming: MetricsInDirection,
32}
33
34impl Display for CombinedMetrics {
35 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
36 write!(
37 f,
38 "metrics: out:\n{}, in:\n{}",
39 self.outgoing, self.incoming
40 )
41 }
42}
43
44pub struct NetworkMetrics {
45 in_datagrams_per_second: RateMetric,
46 in_octets_per_second: RateMetric,
47 out_datagrams_per_second: RateMetric,
48 out_octets_per_second: RateMetric,
49 #[cfg(feature = "log")]
50 last_debug_metric_at: Millis,
51 #[cfg(feature = "log")]
52 debug_metric_duration: MillisDuration,
53}
54
55impl NetworkMetrics {
56 pub fn new(now: Millis) -> Self {
57 Self {
58 in_datagrams_per_second: RateMetric::with_interval(now, 0.1),
59 in_octets_per_second: RateMetric::with_interval(now, 0.1),
60
61 out_datagrams_per_second: RateMetric::with_interval(now, 0.1),
62 out_octets_per_second: RateMetric::with_interval(now, 0.1),
63 #[cfg(feature = "log")]
64 last_debug_metric_at: now,
65 #[cfg(feature = "log")]
66 debug_metric_duration: MillisDuration::from_millis(500),
67 }
68 }
69
70 pub fn sent_datagrams(&mut self, datagrams: &Vec<Vec<u8>>) {
71 for datagram in datagrams {
72 self.out_octets_per_second.add(datagram.len() as u32)
73 }
74 self.out_datagrams_per_second.add(datagrams.len() as u32);
75 }
76
77 pub fn received_datagram(&mut self, datagram: &[u8]) {
78 self.in_octets_per_second.add(datagram.len() as u32);
79 self.in_datagrams_per_second.add(1);
80 }
81
82 pub fn update_metrics(&mut self, now: Millis) {
83 self.in_datagrams_per_second.update(now);
84 self.in_octets_per_second.update(now);
85 self.out_datagrams_per_second.update(now);
86 self.out_octets_per_second.update(now);
87
88 #[cfg(feature = "log")]
89 {
90 use log::debug;
91 if now - self.last_debug_metric_at > self.debug_metric_duration {
92 self.last_debug_metric_at = now;
93 debug!("metrics: {}", self.metrics())
94 }
95 }
96 }
97
98 pub fn metrics(&self) -> CombinedMetrics {
99 CombinedMetrics {
100 outgoing: MetricsInDirection {
101 datagrams_per_second: self.out_datagrams_per_second.rate(),
102 octets_per_second: self.out_octets_per_second.rate(),
103 },
104 incoming: MetricsInDirection {
105 datagrams_per_second: self.in_datagrams_per_second.rate(),
106 octets_per_second: self.in_octets_per_second.rate(),
107 },
108 }
109 }
110
111 pub fn in_datagrams_per_second(&self) -> f32 {
112 self.in_datagrams_per_second.rate()
113 }
114
115 pub fn in_octets_per_second(&self) -> f32 {
116 self.in_octets_per_second.rate()
117 }
118
119 pub fn out_datagrams_per_second(&self) -> f32 {
120 self.out_datagrams_per_second.rate()
121 }
122
123 pub fn out_octets_per_second(&self) -> f32 {
124 self.out_octets_per_second.rate()
125 }
126}