libp2p_scatter/
metrics.rs

1use std::collections::HashMap;
2
3use prometheus_client::metrics::counter::Counter;
4use prometheus_client::metrics::family::Family;
5use prometheus_client::metrics::gauge::Gauge;
6use prometheus_client::registry::Registry;
7
8use crate::Topic;
9
10pub struct Metrics {
11    /// Information needed to decide if a topic is allowed or not.
12    topic_info: HashMap<Topic, EverSubscribed>,
13    /// Status of our subscription to this topic. This metric allows analyzing other topic metrics
14    /// filtered by our current subscription status.
15    topic_subscription_status: Family<Topic, Gauge>,
16    /// Number of peers subscribed to each topic. This allows us to analyze a topic's behaviour
17    /// regardless of our subscription status.
18    topic_peers_count: Family<Topic, Gauge>,
19
20    /// Number of messages sent to each topic.
21    topic_msg_sent_counts: Family<Topic, Counter>,
22    /// Bytes from messages sent to each topic.
23    topic_msg_sent_bytes: Family<Topic, Counter>,
24    /// Number of messages published to each topic.
25    topic_msg_published: Family<Topic, Counter>,
26
27    /// Number of messages received on each topic
28    topic_msg_recv_counts: Family<Topic, Counter>,
29    /// Bytes received from messages for each topic.
30    topic_msg_recv_bytes: Family<Topic, Counter>,
31}
32
33type EverSubscribed = bool;
34
35impl Metrics {
36    pub fn new(registry: &mut Registry) -> Self {
37        macro_rules! register_family {
38            ($name:expr, $help:expr) => {{
39                let fam = Family::default();
40                registry.register($name, $help, fam.clone());
41                fam
42            }};
43        }
44
45        let topic_subscription_status = register_family!(
46            "topic_subscription_status",
47            "Subscription status per known topic"
48        );
49
50        let topic_peers_count = register_family!(
51            "topic_peers_counts",
52            "Number of peers subscribed to each topic"
53        );
54
55        let topic_msg_sent_counts = register_family!(
56            "topic_msg_sent_counts",
57            "Number of gossip messages sent to each topic"
58        );
59        let topic_msg_published = register_family!(
60            "topic_msg_published",
61            "Number of gossip messages published to each topic"
62        );
63        let topic_msg_sent_bytes = register_family!(
64            "topic_msg_sent_bytes",
65            "Bytes from gossip messages sent to each topic"
66        );
67
68        let topic_msg_recv_counts = register_family!(
69            "topic_msg_recv_counts",
70            "Number of gossip messages received on each topic"
71        );
72        let topic_msg_recv_bytes = register_family!(
73            "topic_msg_recv_bytes",
74            "Bytes received from gossip messages for each topic"
75        );
76
77        Self {
78            topic_info: HashMap::new(),
79            topic_subscription_status,
80            topic_peers_count,
81            topic_msg_sent_counts,
82            topic_msg_published,
83            topic_msg_sent_bytes,
84            topic_msg_recv_counts,
85            topic_msg_recv_bytes,
86        }
87    }
88
89    /// Registers a topic if not already known
90    fn register_topic(&mut self, topic: &Topic) {
91        if !self.topic_info.contains_key(topic) {
92            self.topic_info.entry(*topic).or_insert(false);
93            self.topic_subscription_status.get_or_create(topic).set(0);
94        }
95    }
96
97    pub(crate) fn subscribe(&mut self, topic: &Topic) {
98        self.register_topic(topic);
99        self.topic_info.entry(*topic).or_insert(false);
100        self.topic_subscription_status.get_or_create(topic).set(1);
101    }
102
103    pub(crate) fn unsubscribe(&mut self, topic: &Topic) {
104        self.register_topic(topic);
105        self.topic_subscription_status.get_or_create(topic).set(0);
106    }
107
108    /// Increase the number of peers that are subscribed to this topic.
109    pub(crate) fn inc_topic_peers(&mut self, topic: &Topic) {
110        self.register_topic(topic);
111        self.topic_peers_count.get_or_create(topic).inc();
112    }
113
114    /// Decrease the number of peers that are subscribed to this topic.
115    pub(crate) fn dec_topic_peers(&mut self, topic: &Topic) {
116        self.register_topic(topic);
117        self.topic_peers_count.get_or_create(topic).dec();
118    }
119
120    pub(crate) fn register_published_message(&mut self, topic: &Topic) {
121        self.register_topic(topic);
122        self.topic_msg_published.get_or_create(topic).inc();
123    }
124
125    /// Register sending a message over a topic.
126    pub(crate) fn msg_sent(&mut self, topic: &Topic, bytes: usize) {
127        self.register_topic(topic);
128        self.topic_msg_sent_counts.get_or_create(topic).inc();
129        self.topic_msg_sent_bytes
130            .get_or_create(topic)
131            .inc_by(bytes as u64);
132    }
133
134    /// Register that a message was received .
135    pub(crate) fn msg_received(&mut self, topic: &Topic, bytes: usize) {
136        self.register_topic(topic);
137        self.topic_msg_recv_counts.get_or_create(topic).inc();
138        self.topic_msg_recv_bytes
139            .get_or_create(topic)
140            .inc_by(bytes as u64);
141    }
142}