1use std::any::Any;
10#[cfg(feature = "metrics")]
11use std::sync::atomic::{AtomicI64, AtomicU64, Ordering};
12
13use serde::{Deserialize, Serialize};
14
15#[derive(Debug, Clone, Copy, Eq, PartialEq, Serialize, Deserialize)]
17#[non_exhaustive]
18pub enum MetricType {
19 Counter,
21 Gauge,
23}
24
25impl MetricType {
26 pub fn as_str(&self) -> &str {
28 match self {
29 MetricType::Counter => "counter",
30 MetricType::Gauge => "gauge",
31 }
32 }
33}
34
35#[derive(Debug, Clone, Copy, Eq, PartialEq, Serialize, Deserialize)]
37#[non_exhaustive]
38pub enum MetricValue {
39 Counter(u64),
41 Gauge(i64),
43}
44
45impl MetricValue {
46 pub fn to_f32(&self) -> f32 {
48 match self {
49 MetricValue::Counter(value) => *value as f32,
50 MetricValue::Gauge(value) => *value as f32,
51 }
52 }
53
54 pub fn r#type(&self) -> MetricType {
56 match self {
57 MetricValue::Counter(_) => MetricType::Counter,
58 MetricValue::Gauge(_) => MetricType::Gauge,
59 }
60 }
61}
62
63impl Metric for MetricValue {
64 fn r#type(&self) -> MetricType {
65 self.r#type()
66 }
67
68 fn value(&self) -> MetricValue {
69 *self
70 }
71
72 fn as_any(&self) -> &dyn Any {
73 self
74 }
75}
76
77pub trait Metric: std::fmt::Debug {
79 fn r#type(&self) -> MetricType;
81
82 fn value(&self) -> MetricValue;
84
85 fn as_any(&self) -> &dyn Any;
87}
88
89#[derive(Debug, Default, Serialize, Deserialize)]
93pub struct Counter {
94 #[cfg(feature = "metrics")]
96 pub(crate) value: AtomicU64,
97}
98
99impl Metric for Counter {
100 fn value(&self) -> MetricValue {
101 MetricValue::Counter(self.get())
102 }
103
104 fn r#type(&self) -> MetricType {
105 MetricType::Counter
106 }
107
108 fn as_any(&self) -> &dyn Any {
109 self
110 }
111}
112
113impl Counter {
114 pub fn new() -> Self {
116 Self::default()
117 }
118
119 pub fn inc(&self) -> u64 {
121 #[cfg(feature = "metrics")]
122 {
123 self.value.fetch_add(1, Ordering::Relaxed)
124 }
125 #[cfg(not(feature = "metrics"))]
126 0
127 }
128
129 pub fn inc_by(&self, v: u64) -> u64 {
131 #[cfg(feature = "metrics")]
132 {
133 self.value.fetch_add(v, Ordering::Relaxed)
134 }
135 #[cfg(not(feature = "metrics"))]
136 {
137 let _ = v;
138 0
139 }
140 }
141
142 pub fn set(&self, v: u64) -> u64 {
146 #[cfg(feature = "metrics")]
147 {
148 self.value.swap(v, Ordering::Relaxed)
149 }
150 #[cfg(not(feature = "metrics"))]
151 {
152 let _ = v;
153 0
154 }
155 }
156
157 pub fn get(&self) -> u64 {
159 #[cfg(feature = "metrics")]
160 {
161 self.value.load(Ordering::Relaxed)
162 }
163 #[cfg(not(feature = "metrics"))]
164 0
165 }
166}
167
168#[derive(Debug, Default, Serialize, Deserialize)]
170pub struct Gauge {
171 #[cfg(feature = "metrics")]
173 pub(crate) value: AtomicI64,
174}
175
176impl Metric for Gauge {
177 fn r#type(&self) -> MetricType {
178 MetricType::Gauge
179 }
180
181 fn value(&self) -> MetricValue {
182 MetricValue::Gauge(self.get())
183 }
184
185 fn as_any(&self) -> &dyn Any {
186 self
187 }
188}
189
190impl Gauge {
191 pub fn new() -> Self {
193 Self::default()
194 }
195
196 pub fn inc(&self) -> i64 {
198 #[cfg(feature = "metrics")]
199 {
200 self.value.fetch_add(1, Ordering::Relaxed)
201 }
202 #[cfg(not(feature = "metrics"))]
203 0
204 }
205
206 pub fn inc_by(&self, v: i64) -> i64 {
208 #[cfg(feature = "metrics")]
209 {
210 self.value.fetch_add(v, Ordering::Relaxed)
211 }
212 #[cfg(not(feature = "metrics"))]
213 {
214 let _ = v;
215 0
216 }
217 }
218
219 pub fn dec(&self) -> i64 {
221 #[cfg(feature = "metrics")]
222 {
223 self.value.fetch_sub(1, Ordering::Relaxed)
224 }
225 #[cfg(not(feature = "metrics"))]
226 0
227 }
228
229 pub fn dec_by(&self, v: i64) -> i64 {
231 #[cfg(feature = "metrics")]
232 {
233 self.value.fetch_sub(v, Ordering::Relaxed)
234 }
235 #[cfg(not(feature = "metrics"))]
236 {
237 let _ = v;
238 0
239 }
240 }
241
242 pub fn set(&self, v: i64) -> i64 {
244 #[cfg(feature = "metrics")]
245 {
246 self.value.swap(v, Ordering::Relaxed)
247 }
248 #[cfg(not(feature = "metrics"))]
249 {
250 let _ = v;
251 0
252 }
253 }
254
255 pub fn get(&self) -> i64 {
257 #[cfg(feature = "metrics")]
258 {
259 self.value.load(Ordering::Relaxed)
260 }
261 #[cfg(not(feature = "metrics"))]
262 0
263 }
264}