opentelemetry/metrics/instruments/
mod.rs1use gauge::{Gauge, ObservableGauge};
2
3use crate::metrics::Meter;
4use crate::KeyValue;
5use core::fmt;
6use std::borrow::Cow;
7use std::marker;
8
9use super::{
10 Counter, Histogram, InstrumentProvider, ObservableCounter, ObservableUpDownCounter,
11 UpDownCounter,
12};
13
14pub(super) mod counter;
15pub(super) mod gauge;
16pub(super) mod histogram;
17pub(super) mod up_down_counter;
18
19pub trait AsyncInstrument<T>: Send + Sync {
21 fn observe(&self, measurement: T, attributes: &[KeyValue]);
25}
26
27pub trait SyncInstrument<T>: Send + Sync {
29 fn measure(&self, measurement: T, attributes: &[KeyValue]);
31
32 #[cfg(feature = "experimental_metrics_bound_instruments")]
39 fn bind(&self, _attributes: &[KeyValue]) -> Box<dyn BoundSyncInstrument<T> + Send + Sync> {
40 crate::otel_debug!(
41 name: "SyncInstrument.BindNotImplemented",
42 message = "bind() called on a SyncInstrument implementation that does not override the default; measurements through the returned handle will be dropped"
43 );
44 Box::new(crate::metrics::noop::NoopBoundSyncInstrument::new())
45 }
46}
47
48#[cfg(feature = "experimental_metrics_bound_instruments")]
51pub trait BoundSyncInstrument<T>: Send + Sync {
52 fn measure(&self, measurement: T);
54}
55
56#[non_exhaustive] pub struct HistogramBuilder<'a, T> {
59 pub instrument_provider: &'a dyn InstrumentProvider,
61
62 pub name: Cow<'static, str>,
64
65 pub description: Option<Cow<'static, str>>,
67
68 pub unit: Option<Cow<'static, str>>,
70
71 pub boundaries: Option<Vec<f64>>,
73
74 _marker: marker::PhantomData<T>,
76}
77
78impl<'a, T> HistogramBuilder<'a, T> {
79 pub(crate) fn new(meter: &'a Meter, name: Cow<'static, str>) -> Self {
81 HistogramBuilder {
82 instrument_provider: meter.instrument_provider.as_ref(),
83 name,
84 description: None,
85 unit: None,
86 boundaries: None,
87 _marker: marker::PhantomData,
88 }
89 }
90
91 pub fn with_description<S: Into<Cow<'static, str>>>(mut self, description: S) -> Self {
93 self.description = Some(description.into());
94 self
95 }
96
97 pub fn with_unit<S: Into<Cow<'static, str>>>(mut self, unit: S) -> Self {
105 self.unit = Some(unit.into());
106 self
107 }
108
109 pub fn with_boundaries(mut self, boundaries: Vec<f64>) -> Self {
134 self.boundaries = Some(boundaries);
135 self
136 }
137}
138
139impl HistogramBuilder<'_, Histogram<f64>> {
140 pub fn build(self) -> Histogram<f64> {
146 self.instrument_provider.f64_histogram(self)
147 }
148}
149
150impl HistogramBuilder<'_, Histogram<u64>> {
151 pub fn build(self) -> Histogram<u64> {
157 self.instrument_provider.u64_histogram(self)
158 }
159}
160
161#[non_exhaustive] pub struct InstrumentBuilder<'a, T> {
164 pub instrument_provider: &'a dyn InstrumentProvider,
166
167 pub name: Cow<'static, str>,
169
170 pub description: Option<Cow<'static, str>>,
172
173 pub unit: Option<Cow<'static, str>>,
175
176 _marker: marker::PhantomData<T>,
177}
178
179impl<'a, T> InstrumentBuilder<'a, T> {
180 pub(crate) fn new(meter: &'a Meter, name: Cow<'static, str>) -> Self {
182 InstrumentBuilder {
183 instrument_provider: meter.instrument_provider.as_ref(),
184 name,
185 description: None,
186 unit: None,
187 _marker: marker::PhantomData,
188 }
189 }
190
191 pub fn with_description<S: Into<Cow<'static, str>>>(mut self, description: S) -> Self {
193 self.description = Some(description.into());
194 self
195 }
196
197 pub fn with_unit<S: Into<Cow<'static, str>>>(mut self, unit: S) -> Self {
205 self.unit = Some(unit.into());
206 self
207 }
208}
209
210macro_rules! build_instrument {
211 ($name:ident, $inst:ty) => {
212 impl<'a> InstrumentBuilder<'a, $inst> {
213 #[doc = concat!("Validates the instrument configuration and creates a new `", stringify!($inst), "`.")]
214 pub fn build(self) -> $inst {
217 self.instrument_provider.$name(self)
218 }
219 }
220 };
221}
222
223build_instrument!(u64_counter, Counter<u64>);
224build_instrument!(f64_counter, Counter<f64>);
225build_instrument!(u64_gauge, Gauge<u64>);
226build_instrument!(f64_gauge, Gauge<f64>);
227build_instrument!(i64_gauge, Gauge<i64>);
228build_instrument!(i64_up_down_counter, UpDownCounter<i64>);
229build_instrument!(f64_up_down_counter, UpDownCounter<f64>);
230
231impl<T> fmt::Debug for InstrumentBuilder<'_, T> {
232 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
233 f.debug_struct("InstrumentBuilder")
234 .field("name", &self.name)
235 .field("description", &self.description)
236 .field("unit", &self.unit)
237 .field("kind", &std::any::type_name::<T>())
238 .finish()
239 }
240}
241
242impl<T> fmt::Debug for HistogramBuilder<'_, T> {
243 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
244 f.debug_struct("HistogramBuilder")
245 .field("name", &self.name)
246 .field("description", &self.description)
247 .field("unit", &self.unit)
248 .field("boundaries", &self.boundaries)
249 .field(
250 "kind",
251 &format!("Histogram<{}>", &std::any::type_name::<T>()),
252 )
253 .finish()
254 }
255}
256
257pub type Callback<T> = Box<dyn Fn(&dyn AsyncInstrument<T>) + Send + Sync>;
265
266#[must_use = "Callbacks will not be invoked unless you call .build() on this async instrument builder."]
268#[non_exhaustive] pub struct AsyncInstrumentBuilder<'a, I, M> {
270 pub instrument_provider: &'a dyn InstrumentProvider,
272
273 pub name: Cow<'static, str>,
275
276 pub description: Option<Cow<'static, str>>,
278
279 pub unit: Option<Cow<'static, str>>,
281
282 pub callbacks: Vec<Callback<M>>,
284
285 _inst: marker::PhantomData<I>,
286}
287
288impl<'a, I, M> AsyncInstrumentBuilder<'a, I, M> {
289 pub(crate) fn new(meter: &'a Meter, name: Cow<'static, str>) -> Self {
291 AsyncInstrumentBuilder {
292 instrument_provider: meter.instrument_provider.as_ref(),
293 name,
294 description: None,
295 unit: None,
296 _inst: marker::PhantomData,
297 callbacks: Vec::new(),
298 }
299 }
300
301 pub fn with_description<S: Into<Cow<'static, str>>>(mut self, description: S) -> Self {
303 self.description = Some(description.into());
304 self
305 }
306
307 pub fn with_unit<S: Into<Cow<'static, str>>>(mut self, unit: S) -> Self {
315 self.unit = Some(unit.into());
316 self
317 }
318
319 pub fn with_callback<F>(mut self, callback: F) -> Self
321 where
322 F: Fn(&dyn AsyncInstrument<M>) + Send + Sync + 'static,
323 {
324 self.callbacks.push(Box::new(callback));
325 self
326 }
327}
328
329macro_rules! build_async_instrument {
330 ($name:ident, $inst:ty, $measurement:ty) => {
331 impl<'a> AsyncInstrumentBuilder<'a, $inst, $measurement> {
332 #[doc = concat!("Validates the instrument configuration and creates a new `", stringify!($inst), "`.")]
333 pub fn build(self) -> $inst {
336 self.instrument_provider.$name(self)
337 }
338 }
339 };
340}
341
342build_async_instrument!(u64_observable_counter, ObservableCounter<u64>, u64);
343build_async_instrument!(f64_observable_counter, ObservableCounter<f64>, f64);
344build_async_instrument!(u64_observable_gauge, ObservableGauge<u64>, u64);
345build_async_instrument!(f64_observable_gauge, ObservableGauge<f64>, f64);
346build_async_instrument!(i64_observable_gauge, ObservableGauge<i64>, i64);
347build_async_instrument!(
348 i64_observable_up_down_counter,
349 ObservableUpDownCounter<i64>,
350 i64
351);
352build_async_instrument!(
353 f64_observable_up_down_counter,
354 ObservableUpDownCounter<f64>,
355 f64
356);
357
358impl<I, M> fmt::Debug for AsyncInstrumentBuilder<'_, I, M>
359where
360 I: AsyncInstrument<M>,
361{
362 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
363 f.debug_struct("InstrumentBuilder")
364 .field("name", &self.name)
365 .field("description", &self.description)
366 .field("unit", &self.unit)
367 .field("kind", &std::any::type_name::<I>())
368 .field("callbacks_len", &self.callbacks.len())
369 .finish()
370 }
371}