metrics/
counter.rs

1// Copyright 2019 Conflux Foundation. All rights reserved.
2// Conflux is free software and distributed under GNU General Public License.
3// See http://www.gnu.org/licenses/
4
5use crate::{
6    metrics::{is_enabled, Metric, ORDER},
7    registry::{DEFAULT_GROUPING_REGISTRY, DEFAULT_REGISTRY},
8};
9use std::sync::{atomic::AtomicUsize, Arc};
10
11pub trait Counter<T: Default>: Send + Sync {
12    fn count(&self) -> T { T::default() }
13    fn dec(&self, _delta: T) {}
14    fn inc(&self, _delta: T) {}
15}
16
17struct NoopCounter;
18impl<T: Default> Counter<T> for NoopCounter {}
19
20#[macro_export]
21macro_rules! construct_counter {
22    ($name:ident, $value_type:ty, $data_type:ty) => {
23        #[derive(Default)]
24        pub struct $name {
25            value: $value_type,
26        }
27
28        impl $name {
29            pub fn register(name: &str) -> Arc<dyn Counter<$data_type>> {
30                if !is_enabled() {
31                    return Arc::new(NoopCounter);
32                }
33
34                let counter = Arc::new($name::default());
35                DEFAULT_REGISTRY
36                    .write()
37                    .register(name.into(), counter.clone());
38
39                counter
40            }
41
42            pub fn register_with_group(
43                group: &str, name: &str,
44            ) -> Arc<dyn Counter<$data_type>> {
45                if !is_enabled() {
46                    return Arc::new(NoopCounter);
47                }
48
49                let counter = Arc::new($name::default());
50                DEFAULT_GROUPING_REGISTRY.write().register(
51                    group.into(),
52                    name.into(),
53                    counter.clone(),
54                );
55
56                counter
57            }
58        }
59
60        impl Counter<$data_type> for $name {
61            fn count(&self) -> $data_type { self.value.load(ORDER) }
62
63            fn dec(&self, delta: $data_type) {
64                self.value.fetch_sub(delta, ORDER);
65            }
66
67            fn inc(&self, delta: $data_type) {
68                self.value.fetch_add(delta, ORDER);
69            }
70        }
71
72        impl Metric for $name {
73            fn get_type(&self) -> &str { "Counter" }
74        }
75    };
76}
77
78construct_counter!(CounterUsize, AtomicUsize, usize);