network_metrics/
lib.rs

1/*
2 * Copyright (c) Peter Bjorklund. All rights reserved. https://github.com/piot/network-metrics
3 * Licensed under the MIT License. See LICENSE in the project root for license information.
4 */
5
6use 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}