scuffle_metrics/
collector.rs1use std::borrow::Cow;
2
3use opentelemetry::KeyValue;
4
5#[doc(hidden)]
7pub trait IsCollector: private::Sealed {
8 type Builder<'a>;
9
10 fn builder(meter: &opentelemetry::metrics::Meter, name: impl Into<Cow<'static, str>>) -> Self::Builder<'_>;
11}
12
13mod private {
14 pub trait Sealed {
15 type Value;
16 }
17}
18
19macro_rules! impl_collector {
20 ($t:ty, $value:ty, $func:ident, $builder:ty) => {
21 impl private::Sealed for $t {
22 type Value = $value;
23 }
24
25 impl IsCollector for $t {
26 type Builder<'a> = $builder;
27
28 fn builder(meter: &opentelemetry::metrics::Meter, name: impl Into<Cow<'static, str>>) -> Self::Builder<'_> {
29 meter.$func(name)
30 }
31 }
32 };
33}
34
35pub type Counter<T> = opentelemetry::metrics::Counter<T>;
39
40pub type CounterF64 = Counter<f64>;
44
45pub type CounterU64 = Counter<u64>;
49
50impl_collector!(
51 CounterF64,
52 f64,
53 f64_counter,
54 opentelemetry::metrics::InstrumentBuilder<'a, CounterF64>
55);
56impl_collector!(
57 CounterU64,
58 u64,
59 u64_counter,
60 opentelemetry::metrics::InstrumentBuilder<'a, CounterU64>
61);
62
63pub type Gauge<T> = opentelemetry::metrics::Gauge<T>;
68
69pub type GaugeF64 = Gauge<f64>;
75
76pub type GaugeI64 = Gauge<i64>;
82
83pub type GaugeU64 = Gauge<u64>;
89
90impl_collector!(
91 GaugeF64,
92 f64,
93 f64_gauge,
94 opentelemetry::metrics::InstrumentBuilder<'a, GaugeF64>
95);
96impl_collector!(
97 GaugeI64,
98 i64,
99 i64_gauge,
100 opentelemetry::metrics::InstrumentBuilder<'a, GaugeI64>
101);
102impl_collector!(
103 GaugeU64,
104 u64,
105 u64_gauge,
106 opentelemetry::metrics::InstrumentBuilder<'a, GaugeU64>
107);
108
109pub type Histogram<T> = opentelemetry::metrics::Histogram<T>;
113
114pub type HistogramF64 = Histogram<f64>;
118
119pub type HistogramU64 = Histogram<u64>;
123
124impl private::Sealed for HistogramF64 {
125 type Value = f64;
126}
127
128const DEFAULT_BOUNDARIES: [f64; 11] = [0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1.0, 2.5, 5.0, 10.0];
130
131impl IsCollector for HistogramF64 {
132 type Builder<'a> = opentelemetry::metrics::HistogramBuilder<'a, HistogramF64>;
133
134 fn builder(meter: &opentelemetry::metrics::Meter, name: impl Into<Cow<'static, str>>) -> Self::Builder<'_> {
135 meter.f64_histogram(name).with_boundaries(DEFAULT_BOUNDARIES.into())
136 }
137}
138
139impl private::Sealed for HistogramU64 {
140 type Value = u64;
141}
142
143impl IsCollector for HistogramU64 {
144 type Builder<'a> = opentelemetry::metrics::HistogramBuilder<'a, HistogramU64>;
145
146 fn builder(meter: &opentelemetry::metrics::Meter, name: impl Into<Cow<'static, str>>) -> Self::Builder<'_> {
147 meter.u64_histogram(name).with_boundaries(DEFAULT_BOUNDARIES.into())
148 }
149}
150
151pub type UpDownCounter<T> = opentelemetry::metrics::UpDownCounter<T>;
156
157pub type UpDownCounterI64 = UpDownCounter<i64>;
161
162pub type UpDownCounterF64 = UpDownCounter<f64>;
166
167impl_collector!(
168 UpDownCounterI64,
169 i64,
170 i64_up_down_counter,
171 opentelemetry::metrics::InstrumentBuilder<'a, UpDownCounterI64>
172);
173impl_collector!(
174 UpDownCounterF64,
175 f64,
176 f64_up_down_counter,
177 opentelemetry::metrics::InstrumentBuilder<'a, UpDownCounterF64>
178);
179
180trait Number {
183 const ONE: Self;
184}
185
186impl Number for f64 {
187 const ONE: Self = 1.0;
188}
189
190impl Number for u64 {
191 const ONE: Self = 1;
192}
193
194impl Number for i64 {
195 const ONE: Self = 1;
196}
197
198#[must_use = "Collectors do nothing by themselves, you must call them"]
202pub struct Collector<'a, T: IsCollector> {
203 attributes: Vec<KeyValue>,
204 collector: &'a T,
205}
206
207impl<'a, T: IsCollector> Collector<'a, T> {
208 pub fn new(attributes: Vec<KeyValue>, collector: &'a T) -> Self {
213 Self { attributes, collector }
214 }
215
216 pub fn inner(&self) -> &'a T {
218 self.collector
219 }
220}
221
222macro_rules! impl_counter {
223 ($t:ty) => {
224 impl<'a> Collector<'a, opentelemetry::metrics::Counter<$t>> {
225 #[inline]
227 pub fn incr(&self) {
228 self.incr_by(<$t as Number>::ONE);
229 }
230
231 pub fn incr_by(&self, value: $t) {
233 self.collector.add(value, &self.attributes);
234 }
235 }
236 };
237}
238
239impl_counter!(u64);
240impl_counter!(f64);
241
242macro_rules! impl_gauge {
243 ($t:ty) => {
244 impl<'a> Collector<'a, opentelemetry::metrics::Gauge<$t>> {
245 pub fn record(&self, value: $t) {
247 self.collector.record(value, &self.attributes);
248 }
249 }
250 };
251}
252
253impl_gauge!(u64);
254impl_gauge!(f64);
255impl_gauge!(i64);
256
257macro_rules! impl_histogram {
258 ($t:ty) => {
259 impl<'a> Collector<'a, opentelemetry::metrics::Histogram<$t>> {
260 pub fn observe(&self, value: $t) {
262 self.collector.record(value, &self.attributes);
263 }
264 }
265 };
266}
267
268impl_histogram!(u64);
269impl_histogram!(f64);
270
271macro_rules! impl_updowncounter {
272 ($t:ty) => {
273 impl<'a> Collector<'a, opentelemetry::metrics::UpDownCounter<$t>> {
274 pub fn incr(&self) {
276 self.incr_by(<$t as Number>::ONE);
277 }
278
279 pub fn incr_by(&self, value: $t) {
281 self.collector.add(value, &self.attributes);
282 }
283
284 pub fn decr(&self) {
286 self.decr_by(<$t as Number>::ONE);
287 }
288
289 pub fn decr_by(&self, value: $t) {
291 self.collector.add(-value, &self.attributes);
292 }
293 }
294 };
295}
296
297impl_updowncounter!(i64);
298impl_updowncounter!(f64);