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")]
52pub trait BoundSyncInstrument<T>: Send + Sync {
53 fn measure(&self, measurement: T);
55}
56
57#[non_exhaustive] pub struct HistogramBuilder<'a, T> {
60 pub instrument_provider: &'a dyn InstrumentProvider,
62
63 pub name: Cow<'static, str>,
65
66 pub description: Option<Cow<'static, str>>,
68
69 pub unit: Option<Cow<'static, str>>,
71
72 pub boundaries: Option<Vec<f64>>,
74
75 _marker: marker::PhantomData<T>,
77}
78
79impl<'a, T> HistogramBuilder<'a, T> {
80 pub(crate) fn new(meter: &'a Meter, name: Cow<'static, str>) -> Self {
82 HistogramBuilder {
83 instrument_provider: meter.instrument_provider.as_ref(),
84 name,
85 description: None,
86 unit: None,
87 boundaries: None,
88 _marker: marker::PhantomData,
89 }
90 }
91
92 pub fn with_description<S: Into<Cow<'static, str>>>(mut self, description: S) -> Self {
94 self.description = Some(description.into());
95 self
96 }
97
98 pub fn with_unit<S: Into<Cow<'static, str>>>(mut self, unit: S) -> Self {
106 self.unit = Some(unit.into());
107 self
108 }
109
110 pub fn with_boundaries(mut self, boundaries: Vec<f64>) -> Self {
135 self.boundaries = Some(boundaries);
136 self
137 }
138}
139
140impl HistogramBuilder<'_, Histogram<f64>> {
141 pub fn build(self) -> Histogram<f64> {
147 self.instrument_provider.f64_histogram(self)
148 }
149}
150
151impl HistogramBuilder<'_, Histogram<u64>> {
152 pub fn build(self) -> Histogram<u64> {
158 self.instrument_provider.u64_histogram(self)
159 }
160}
161
162#[non_exhaustive] pub struct InstrumentBuilder<'a, T> {
165 pub instrument_provider: &'a dyn InstrumentProvider,
167
168 pub name: Cow<'static, str>,
170
171 pub description: Option<Cow<'static, str>>,
173
174 pub unit: Option<Cow<'static, str>>,
176
177 _marker: marker::PhantomData<T>,
178}
179
180impl<'a, T> InstrumentBuilder<'a, T> {
181 pub(crate) fn new(meter: &'a Meter, name: Cow<'static, str>) -> Self {
183 InstrumentBuilder {
184 instrument_provider: meter.instrument_provider.as_ref(),
185 name,
186 description: None,
187 unit: None,
188 _marker: marker::PhantomData,
189 }
190 }
191
192 pub fn with_description<S: Into<Cow<'static, str>>>(mut self, description: S) -> Self {
194 self.description = Some(description.into());
195 self
196 }
197
198 pub fn with_unit<S: Into<Cow<'static, str>>>(mut self, unit: S) -> Self {
206 self.unit = Some(unit.into());
207 self
208 }
209}
210
211macro_rules! build_instrument {
212 ($name:ident, $inst:ty) => {
213 impl<'a> InstrumentBuilder<'a, $inst> {
214 #[doc = concat!("Validates the instrument configuration and creates a new `", stringify!($inst), "`.")]
215 pub fn build(self) -> $inst {
218 self.instrument_provider.$name(self)
219 }
220 }
221 };
222}
223
224build_instrument!(u64_counter, Counter<u64>);
225build_instrument!(f64_counter, Counter<f64>);
226build_instrument!(u64_gauge, Gauge<u64>);
227build_instrument!(f64_gauge, Gauge<f64>);
228build_instrument!(i64_gauge, Gauge<i64>);
229build_instrument!(i64_up_down_counter, UpDownCounter<i64>);
230build_instrument!(f64_up_down_counter, UpDownCounter<f64>);
231
232impl<T> fmt::Debug for InstrumentBuilder<'_, T> {
233 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
234 f.debug_struct("InstrumentBuilder")
235 .field("name", &self.name)
236 .field("description", &self.description)
237 .field("unit", &self.unit)
238 .field("kind", &std::any::type_name::<T>())
239 .finish()
240 }
241}
242
243impl<T> fmt::Debug for HistogramBuilder<'_, T> {
244 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
245 f.debug_struct("HistogramBuilder")
246 .field("name", &self.name)
247 .field("description", &self.description)
248 .field("unit", &self.unit)
249 .field("boundaries", &self.boundaries)
250 .field(
251 "kind",
252 &format!("Histogram<{}>", std::any::type_name::<T>()),
253 )
254 .finish()
255 }
256}
257
258pub type Callback<T> = Box<dyn Fn(&dyn AsyncInstrument<T>) + Send + Sync>;
273
274#[must_use = "Callbacks will not be invoked unless you call .build() on this async instrument builder."]
276#[non_exhaustive] pub struct AsyncInstrumentBuilder<'a, I, M> {
278 pub instrument_provider: &'a dyn InstrumentProvider,
280
281 pub name: Cow<'static, str>,
283
284 pub description: Option<Cow<'static, str>>,
286
287 pub unit: Option<Cow<'static, str>>,
289
290 pub callbacks: Vec<Callback<M>>,
292
293 _inst: marker::PhantomData<I>,
294}
295
296impl<'a, I, M> AsyncInstrumentBuilder<'a, I, M> {
297 pub(crate) fn new(meter: &'a Meter, name: Cow<'static, str>) -> Self {
299 AsyncInstrumentBuilder {
300 instrument_provider: meter.instrument_provider.as_ref(),
301 name,
302 description: None,
303 unit: None,
304 _inst: marker::PhantomData,
305 callbacks: Vec::new(),
306 }
307 }
308
309 pub fn with_description<S: Into<Cow<'static, str>>>(mut self, description: S) -> Self {
311 self.description = Some(description.into());
312 self
313 }
314
315 pub fn with_unit<S: Into<Cow<'static, str>>>(mut self, unit: S) -> Self {
323 self.unit = Some(unit.into());
324 self
325 }
326
327 pub fn with_callback<F>(mut self, callback: F) -> Self
335 where
336 F: Fn(&dyn AsyncInstrument<M>) + Send + Sync + 'static,
337 {
338 self.callbacks.push(Box::new(callback));
339 self
340 }
341}
342
343macro_rules! build_async_instrument {
344 ($name:ident, $inst:ty, $measurement:ty) => {
345 impl<'a> AsyncInstrumentBuilder<'a, $inst, $measurement> {
346 #[doc = concat!("Validates the instrument configuration and creates a new `", stringify!($inst), "`.")]
347 pub fn build(self) -> $inst {
350 self.instrument_provider.$name(self)
351 }
352 }
353 };
354}
355
356build_async_instrument!(u64_observable_counter, ObservableCounter<u64>, u64);
357build_async_instrument!(f64_observable_counter, ObservableCounter<f64>, f64);
358build_async_instrument!(u64_observable_gauge, ObservableGauge<u64>, u64);
359build_async_instrument!(f64_observable_gauge, ObservableGauge<f64>, f64);
360build_async_instrument!(i64_observable_gauge, ObservableGauge<i64>, i64);
361build_async_instrument!(
362 i64_observable_up_down_counter,
363 ObservableUpDownCounter<i64>,
364 i64
365);
366build_async_instrument!(
367 f64_observable_up_down_counter,
368 ObservableUpDownCounter<f64>,
369 f64
370);
371
372impl<I, M> fmt::Debug for AsyncInstrumentBuilder<'_, I, M>
373where
374 I: AsyncInstrument<M>,
375{
376 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
377 f.debug_struct("InstrumentBuilder")
378 .field("name", &self.name)
379 .field("description", &self.description)
380 .field("unit", &self.unit)
381 .field("kind", &std::any::type_name::<I>())
382 .field("callbacks_len", &self.callbacks.len())
383 .finish()
384 }
385}