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>;
266
267#[must_use = "Callbacks will not be invoked unless you call .build() on this async instrument builder."]
269#[non_exhaustive] pub struct AsyncInstrumentBuilder<'a, I, M> {
271 pub instrument_provider: &'a dyn InstrumentProvider,
273
274 pub name: Cow<'static, str>,
276
277 pub description: Option<Cow<'static, str>>,
279
280 pub unit: Option<Cow<'static, str>>,
282
283 pub callbacks: Vec<Callback<M>>,
285
286 _inst: marker::PhantomData<I>,
287}
288
289impl<'a, I, M> AsyncInstrumentBuilder<'a, I, M> {
290 pub(crate) fn new(meter: &'a Meter, name: Cow<'static, str>) -> Self {
292 AsyncInstrumentBuilder {
293 instrument_provider: meter.instrument_provider.as_ref(),
294 name,
295 description: None,
296 unit: None,
297 _inst: marker::PhantomData,
298 callbacks: Vec::new(),
299 }
300 }
301
302 pub fn with_description<S: Into<Cow<'static, str>>>(mut self, description: S) -> Self {
304 self.description = Some(description.into());
305 self
306 }
307
308 pub fn with_unit<S: Into<Cow<'static, str>>>(mut self, unit: S) -> Self {
316 self.unit = Some(unit.into());
317 self
318 }
319
320 pub fn with_callback<F>(mut self, callback: F) -> Self
322 where
323 F: Fn(&dyn AsyncInstrument<M>) + Send + Sync + 'static,
324 {
325 self.callbacks.push(Box::new(callback));
326 self
327 }
328}
329
330macro_rules! build_async_instrument {
331 ($name:ident, $inst:ty, $measurement:ty) => {
332 impl<'a> AsyncInstrumentBuilder<'a, $inst, $measurement> {
333 #[doc = concat!("Validates the instrument configuration and creates a new `", stringify!($inst), "`.")]
334 pub fn build(self) -> $inst {
337 self.instrument_provider.$name(self)
338 }
339 }
340 };
341}
342
343build_async_instrument!(u64_observable_counter, ObservableCounter<u64>, u64);
344build_async_instrument!(f64_observable_counter, ObservableCounter<f64>, f64);
345build_async_instrument!(u64_observable_gauge, ObservableGauge<u64>, u64);
346build_async_instrument!(f64_observable_gauge, ObservableGauge<f64>, f64);
347build_async_instrument!(i64_observable_gauge, ObservableGauge<i64>, i64);
348build_async_instrument!(
349 i64_observable_up_down_counter,
350 ObservableUpDownCounter<i64>,
351 i64
352);
353build_async_instrument!(
354 f64_observable_up_down_counter,
355 ObservableUpDownCounter<f64>,
356 f64
357);
358
359impl<I, M> fmt::Debug for AsyncInstrumentBuilder<'_, I, M>
360where
361 I: AsyncInstrument<M>,
362{
363 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
364 f.debug_struct("InstrumentBuilder")
365 .field("name", &self.name)
366 .field("description", &self.description)
367 .field("unit", &self.unit)
368 .field("kind", &std::any::type_name::<I>())
369 .field("callbacks_len", &self.callbacks.len())
370 .finish()
371 }
372}