1use 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);