1#![deny(missing_docs)]
5
6pub mod tracing;
9
10use std::borrow::Cow;
11use std::sync::Arc;
12
13use parking_lot::Mutex;
14
15mod counter;
16mod gauge;
17mod histogram;
18mod timer;
19
20pub use counter::*;
21pub use gauge::*;
22pub use histogram::*;
23pub use timer::*;
24
25#[derive(Clone, Debug)]
27pub struct Label {
28 key: Cow<'static, str>,
29 value: Cow<'static, str>,
30}
31
32impl std::fmt::Display for Label {
33 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
34 write!(f, "{}={}", self.key, self.value)
35 }
36}
37
38impl<K, V> From<(K, V)> for Label
39where
40 K: Into<Cow<'static, str>>,
41 V: Into<Cow<'static, str>>,
42{
43 fn from(value: (K, V)) -> Self {
44 Label::new(value.0, value.1)
45 }
46}
47
48impl Label {
49 pub fn new(key: impl Into<Cow<'static, str>>, value: impl Into<Cow<'static, str>>) -> Self {
51 Self {
52 key: key.into(),
53 value: value.into(),
54 }
55 }
56
57 pub fn key(&self) -> &str {
59 &self.key
60 }
61
62 pub fn value(&self) -> &str {
64 &self.value
65 }
66}
67
68pub trait MetricsRegistry: Send + Sync {
72 fn register_counter(&self, name: Cow<'static, str>, labels: Vec<Label>) -> Counter;
74
75 fn register_histogram(&self, name: Cow<'static, str>, labels: Vec<Label>) -> Histogram;
77
78 fn register_timer(&self, name: Cow<'static, str>, labels: Vec<Label>) -> Timer;
80
81 fn register_gauge(&self, name: Cow<'static, str>, labels: Vec<Label>) -> Gauge;
83
84 fn snapshot(&self) -> Vec<Metric>;
87}
88
89pub struct MetricBuilder<'s> {
91 labels: Vec<Label>,
92 registry: &'s dyn MetricsRegistry,
93}
94
95impl<'r> MetricBuilder<'r> {
96 pub fn new(registry: &'r dyn MetricsRegistry) -> Self {
98 Self {
99 labels: vec![],
100 registry,
101 }
102 }
103
104 pub fn add_label<K, V>(mut self, key: K, value: V) -> Self
106 where
107 K: Into<Cow<'static, str>>,
108 V: Into<Cow<'static, str>>,
109 {
110 self.labels.push(Label::new(key, value));
111 self
112 }
113
114 pub fn add_labels<I, L>(mut self, labels: I) -> Self
116 where
117 I: IntoIterator<Item = L>,
118 L: Into<Label>,
119 {
120 self.labels.extend(labels.into_iter().map(|l| l.into()));
121 self
122 }
123
124 pub fn counter(self, name: impl Into<Cow<'static, str>>) -> Counter {
126 self.registry.register_counter(name.into(), self.labels)
127 }
128
129 pub fn histogram(self, name: impl Into<Cow<'static, str>>) -> Histogram {
131 self.registry.register_histogram(name.into(), self.labels)
132 }
133
134 pub fn timer(self, name: impl Into<Cow<'static, str>>) -> Timer {
136 self.registry.register_timer(name.into(), self.labels)
137 }
138
139 pub fn gauge(self, name: impl Into<Cow<'static, str>>) -> Gauge {
141 self.registry.register_gauge(name.into(), self.labels)
142 }
143}
144
145#[derive(Default, Clone)]
147pub struct DefaultMetricsRegistry {
148 inner: Arc<Mutex<Vec<Metric>>>,
149}
150
151#[derive(Clone, Debug)]
152pub enum MetricValue {
154 Counter(Counter),
156 Histogram(Histogram),
158 Timer(Timer),
160 Gauge(Gauge),
162}
163
164impl From<Counter> for MetricValue {
165 fn from(value: Counter) -> Self {
166 Self::Counter(value)
167 }
168}
169
170impl From<Histogram> for MetricValue {
171 fn from(value: Histogram) -> Self {
172 Self::Histogram(value)
173 }
174}
175
176impl From<Timer> for MetricValue {
177 fn from(value: Timer) -> Self {
178 Self::Timer(value)
179 }
180}
181
182impl From<Gauge> for MetricValue {
183 fn from(value: Gauge) -> Self {
184 Self::Gauge(value)
185 }
186}
187
188#[derive(Clone, Debug)]
190pub struct Metric {
191 name: Cow<'static, str>,
192 labels: Vec<Label>,
193 value: MetricValue,
194}
195
196impl Metric {
197 pub fn name(&self) -> &Cow<'static, str> {
199 &self.name
200 }
201
202 pub fn labels(&self) -> &[Label] {
204 &self.labels
205 }
206
207 pub fn value(&self) -> &MetricValue {
209 &self.value
210 }
211}
212
213impl MetricsRegistry for DefaultMetricsRegistry {
214 fn register_counter(&self, name: Cow<'static, str>, labels: Vec<Label>) -> Counter {
215 let counter = Counter::new();
216 let metric = Metric {
217 name,
218 labels,
219 value: counter.clone().into(),
220 };
221 self.inner.lock().push(metric);
222 counter
223 }
224
225 fn register_histogram(&self, name: Cow<'static, str>, labels: Vec<Label>) -> Histogram {
226 let histogram = Histogram::new();
227 let metric = Metric {
228 name,
229 labels,
230 value: histogram.clone().into(),
231 };
232 self.inner.lock().push(metric);
233 histogram
234 }
235
236 fn register_timer(&self, name: Cow<'static, str>, labels: Vec<Label>) -> Timer {
237 let timer = Timer::new();
238 let metric = Metric {
239 name,
240 labels,
241 value: timer.clone().into(),
242 };
243 self.inner.lock().push(metric);
244 timer
245 }
246
247 fn register_gauge(&self, name: Cow<'static, str>, labels: Vec<Label>) -> Gauge {
248 let gauge = Gauge::new();
249 let metric = Metric {
250 name,
251 labels,
252 value: gauge.clone().into(),
253 };
254 self.inner.lock().push(metric);
255 gauge
256 }
257
258 fn snapshot(&self) -> Vec<Metric> {
259 self.inner.lock().clone()
260 }
261}