opentelemetry/metrics/
meter.rs

1use core::fmt;
2use std::any::Any;
3use std::borrow::Cow;
4use std::sync::Arc;
5
6use crate::metrics::{
7    AsyncInstrumentBuilder, Counter, Gauge, Histogram, InstrumentBuilder, InstrumentProvider,
8    ObservableCounter, ObservableGauge, ObservableUpDownCounter, Result, UpDownCounter,
9};
10use crate::KeyValue;
11
12use super::AsyncInstrument;
13
14/// Provides access to named [Meter] instances, for instrumenting an application
15/// or crate.
16pub trait MeterProvider {
17    /// Returns a new [Meter] with the provided name and default configuration.
18    ///
19    /// A [Meter] should be scoped at most to a single application or crate. The
20    /// name needs to be unique so it does not collide with other names used by
21    /// an application, nor other applications.
22    ///
23    /// If the name is empty, then an implementation defined default name will
24    /// be used instead.
25    ///
26    /// # Examples
27    ///
28    /// ```
29    /// use opentelemetry::{global, metrics::MeterProvider};
30    /// use opentelemetry::KeyValue;
31    ///
32    /// let provider = global::meter_provider();
33    ///
34    /// // meter used in applications
35    /// let meter = provider.meter("my_app");
36    ///
37    /// // meter used in libraries/crates that optionally includes version and schema url
38    /// let meter = provider.versioned_meter(
39    ///     "my_library",
40    ///     Some(env!("CARGO_PKG_VERSION")),
41    ///     Some("https://opentelemetry.io/schema/1.0.0"),
42    ///     Some(vec![KeyValue::new("key", "value")]),
43    /// );
44    /// ```
45    fn meter(&self, name: impl Into<Cow<'static, str>>) -> Meter {
46        self.versioned_meter(
47            name,
48            None::<Cow<'static, str>>,
49            None::<Cow<'static, str>>,
50            None,
51        )
52    }
53
54    /// Returns a new versioned meter with a given name.
55    ///
56    /// The instrumentation name must be the name of the library providing instrumentation. This
57    /// name may be the same as the instrumented code only if that code provides built-in
58    /// instrumentation. If the instrumentation name is empty, then a implementation defined
59    /// default name will be used instead.
60    fn versioned_meter(
61        &self,
62        name: impl Into<Cow<'static, str>>,
63        version: Option<impl Into<Cow<'static, str>>>,
64        schema_url: Option<impl Into<Cow<'static, str>>>,
65        attributes: Option<Vec<KeyValue>>,
66    ) -> Meter;
67}
68
69/// Provides access to instrument instances for recording measurements.
70///
71/// ```
72/// use opentelemetry::{global, KeyValue};
73///
74/// let meter = global::meter("my-meter");
75///
76/// // Meters can create metric instruments that can record values of type u64 and f64
77///
78/// // u64 Counter
79/// let u64_counter = meter.u64_counter("my_u64_counter").init();
80///
81/// // Record measurements using the counter instrument add()
82/// u64_counter.add(
83///     10,
84///     &[
85///         KeyValue::new("mykey1", "myvalue1"),
86///         KeyValue::new("mykey2", "myvalue2"),
87///     ]
88/// );
89///
90/// // f64 Counter
91/// let f64_counter = meter.f64_counter("my_f64_counter").init();
92///
93/// // Record measurements using the counter instrument add()
94/// f64_counter.add(
95///     3.15,
96///     &[
97///         KeyValue::new("mykey1", "myvalue1"),
98///         KeyValue::new("mykey2", "myvalue2"),
99///     ],
100/// );
101///
102/// // u6 observable counter
103/// let observable_u4_counter = meter.u64_observable_counter("my_observable_u64_counter").init();
104///
105/// // Register a callback to this meter for an asynchronous instrument to record measurements
106/// meter.register_callback(&[observable_u4_counter.as_any()], move |observer| {
107///     observer.observe_u64(
108///         &observable_u4_counter,
109///         1,
110///         &[
111///             KeyValue::new("mykey1", "myvalue1"),
112///             KeyValue::new("mykey2", "myvalue2"),
113///         ],
114///     )
115/// });
116///
117/// // f64 observable counter
118/// let observable_f64_counter = meter.f64_observable_counter("my_observable_f64_counter").init();
119///
120/// // Register a callback to this meter for an asynchronous instrument to record measurements
121/// meter.register_callback(&[observable_f64_counter.as_any()], move |observer| {
122///     observer.observe_f64(
123///         &observable_f64_counter,
124///         1.55,
125///         &[
126///             KeyValue::new("mykey1", "myvalue1"),
127///             KeyValue::new("mykey2", "myvalue2"),
128///         ],
129///     )
130/// });
131///
132/// // i64 updown counter
133/// let updown_i64_counter = meter.i64_up_down_counter("my_updown_i64_counter").init();
134///
135/// // Record measurements using the updown counter instrument add()
136/// updown_i64_counter.add(
137///     -10,
138///     &
139///     [
140///         KeyValue::new("mykey1", "myvalue1"),
141///         KeyValue::new("mykey2", "myvalue2"),
142///     ],
143/// );
144///
145/// // f64 updown counter
146/// let updown_f64_counter = meter.f64_up_down_counter("my_updown_f64_counter").init();
147///
148/// // Record measurements using the updown counter instrument add()
149/// updown_f64_counter.add(
150///     -10.67,
151///     &
152///     [
153///         KeyValue::new("mykey1", "myvalue1"),
154///         KeyValue::new("mykey2", "myvalue2"),
155///     ],
156/// );
157///
158/// // i64 observable updown counter
159/// let observable_i64_up_down_counter = meter.i64_observable_up_down_counter("my_observable_i64_updown_counter").init();
160///
161/// // Register a callback to this meter for an asynchronous instrument to record measurements
162/// meter.register_callback(&[observable_i64_up_down_counter.as_any()], move |observer| {
163///     observer.observe_i64(
164///         &observable_i64_up_down_counter,
165///         1,
166///         &[
167///             KeyValue::new("mykey1", "myvalue1"),
168///             KeyValue::new("mykey2", "myvalue2"),
169///         ],
170///     )
171/// });
172///
173/// // f64 observable updown counter
174/// let observable_f64_up_down_counter = meter.f64_observable_up_down_counter("my_observable_f64_updown_counter").init();
175///
176/// // Register a callback to this meter for an asynchronous instrument to record measurements
177/// meter.register_callback(&[observable_f64_up_down_counter.as_any()], move |observer| {
178///     observer.observe_f64(
179///         &observable_f64_up_down_counter,
180///         1.16,
181///         &[
182///             KeyValue::new("mykey1", "myvalue1"),
183///             KeyValue::new("mykey2", "myvalue2"),
184///         ],
185///     )
186/// });
187///
188/// // Observable f64 gauge
189/// let f64_gauge = meter.f64_observable_gauge("my_f64_gauge").init();
190///
191/// // Register a callback to this meter for an asynchronous instrument to record measurements
192/// meter.register_callback(&[f64_gauge.as_any()], move |observer| {
193///     observer.observe_f64(
194///         &f64_gauge,
195///         2.32,
196///         &[
197///             KeyValue::new("mykey1", "myvalue1"),
198///             KeyValue::new("mykey2", "myvalue2"),
199///         ],
200///     )
201/// });
202///
203/// // Observable i64 gauge
204/// let i64_gauge = meter.i64_observable_gauge("my_i64_gauge").init();
205///
206/// // Register a callback to this meter for an asynchronous instrument to record measurements
207/// meter.register_callback(&[i64_gauge.as_any()], move |observer| {
208///     observer.observe_i64(
209///         &i64_gauge,
210///         12,
211///         &[
212///             KeyValue::new("mykey1", "myvalue1"),
213///             KeyValue::new("mykey2", "myvalue2"),
214///         ],
215///     )
216/// });
217///
218/// // Observable u64 gauge
219/// let u64_gauge = meter.u64_observable_gauge("my_u64_gauge").init();
220///
221/// // Register a callback to this meter for an asynchronous instrument to record measurements
222/// meter.register_callback(&[u64_gauge.as_any()], move |observer| {
223///     observer.observe_u64(
224///         &u64_gauge,
225///         1,
226///         &[
227///             KeyValue::new("mykey1", "myvalue1"),
228///             KeyValue::new("mykey2", "myvalue2"),
229///         ],
230///     )
231/// });
232///
233/// // f64 histogram
234/// let f64_histogram = meter.f64_histogram("my_f64_histogram").init();
235///
236/// // Record measurements using the histogram instrument record()
237/// f64_histogram.record(
238///     10.5,
239///     &[
240///         KeyValue::new("mykey1", "myvalue1"),
241///         KeyValue::new("mykey2", "myvalue2"),
242///     ],
243/// );
244///
245/// // u64 histogram
246/// let u64_histogram = meter.u64_histogram("my_u64_histogram").init();
247///
248/// // Record measurements using the histogram instrument record()
249/// u64_histogram.record(
250///     12,
251///     &[
252///         KeyValue::new("mykey1", "myvalue1"),
253///         KeyValue::new("mykey2", "myvalue2"),
254///     ],
255/// );
256///
257/// ```
258#[derive(Clone)]
259pub struct Meter {
260    pub(crate) instrument_provider: Arc<dyn InstrumentProvider + Send + Sync>,
261}
262
263impl Meter {
264    /// Create a new named meter from an instrumentation provider
265    #[doc(hidden)]
266    pub fn new(instrument_provider: Arc<dyn InstrumentProvider + Send + Sync>) -> Self {
267        Meter {
268            instrument_provider,
269        }
270    }
271
272    /// creates an instrument builder for recording increasing values.
273    pub fn u64_counter(
274        &self,
275        name: impl Into<Cow<'static, str>>,
276    ) -> InstrumentBuilder<'_, Counter<u64>> {
277        InstrumentBuilder::new(self, name.into())
278    }
279
280    /// creates an instrument builder for recording increasing values.
281    pub fn f64_counter(
282        &self,
283        name: impl Into<Cow<'static, str>>,
284    ) -> InstrumentBuilder<'_, Counter<f64>> {
285        InstrumentBuilder::new(self, name.into())
286    }
287
288    /// creates an instrument builder for recording increasing values via callback.
289    pub fn u64_observable_counter(
290        &self,
291        name: impl Into<Cow<'static, str>>,
292    ) -> AsyncInstrumentBuilder<'_, ObservableCounter<u64>, u64> {
293        AsyncInstrumentBuilder::new(self, name.into())
294    }
295
296    /// creates an instrument builder for recording increasing values via callback.
297    pub fn f64_observable_counter(
298        &self,
299        name: impl Into<Cow<'static, str>>,
300    ) -> AsyncInstrumentBuilder<'_, ObservableCounter<f64>, f64> {
301        AsyncInstrumentBuilder::new(self, name.into())
302    }
303
304    /// creates an instrument builder for recording changes of a value.
305    pub fn i64_up_down_counter(
306        &self,
307        name: impl Into<Cow<'static, str>>,
308    ) -> InstrumentBuilder<'_, UpDownCounter<i64>> {
309        InstrumentBuilder::new(self, name.into())
310    }
311
312    /// creates an instrument builder for recording changes of a value.
313    pub fn f64_up_down_counter(
314        &self,
315        name: impl Into<Cow<'static, str>>,
316    ) -> InstrumentBuilder<'_, UpDownCounter<f64>> {
317        InstrumentBuilder::new(self, name.into())
318    }
319
320    /// creates an instrument builder for recording changes of a value via callback.
321    pub fn i64_observable_up_down_counter(
322        &self,
323        name: impl Into<Cow<'static, str>>,
324    ) -> AsyncInstrumentBuilder<'_, ObservableUpDownCounter<i64>, i64> {
325        AsyncInstrumentBuilder::new(self, name.into())
326    }
327
328    /// creates an instrument builder for recording changes of a value via callback.
329    pub fn f64_observable_up_down_counter(
330        &self,
331        name: impl Into<Cow<'static, str>>,
332    ) -> AsyncInstrumentBuilder<'_, ObservableUpDownCounter<f64>, f64> {
333        AsyncInstrumentBuilder::new(self, name.into())
334    }
335
336    /// creates an instrument builder for recording independent values.
337    pub fn u64_gauge(
338        &self,
339        name: impl Into<Cow<'static, str>>,
340    ) -> InstrumentBuilder<'_, Gauge<u64>> {
341        InstrumentBuilder::new(self, name.into())
342    }
343
344    /// creates an instrument builder for recording independent values.
345    pub fn f64_gauge(
346        &self,
347        name: impl Into<Cow<'static, str>>,
348    ) -> InstrumentBuilder<'_, Gauge<f64>> {
349        InstrumentBuilder::new(self, name.into())
350    }
351
352    /// creates an instrument builder for recording independent values.
353    pub fn i64_gauge(
354        &self,
355        name: impl Into<Cow<'static, str>>,
356    ) -> InstrumentBuilder<'_, Gauge<i64>> {
357        InstrumentBuilder::new(self, name.into())
358    }
359
360    /// creates an instrument builder for recording the current value via callback.
361    pub fn u64_observable_gauge(
362        &self,
363        name: impl Into<Cow<'static, str>>,
364    ) -> AsyncInstrumentBuilder<'_, ObservableGauge<u64>, u64> {
365        AsyncInstrumentBuilder::new(self, name.into())
366    }
367
368    /// creates an instrument builder for recording the current value via callback.
369    pub fn i64_observable_gauge(
370        &self,
371        name: impl Into<Cow<'static, str>>,
372    ) -> AsyncInstrumentBuilder<'_, ObservableGauge<i64>, i64> {
373        AsyncInstrumentBuilder::new(self, name.into())
374    }
375
376    /// creates an instrument builder for recording the current value via callback.
377    pub fn f64_observable_gauge(
378        &self,
379        name: impl Into<Cow<'static, str>>,
380    ) -> AsyncInstrumentBuilder<'_, ObservableGauge<f64>, f64> {
381        AsyncInstrumentBuilder::new(self, name.into())
382    }
383
384    /// creates an instrument builder for recording a distribution of values.
385    pub fn f64_histogram(
386        &self,
387        name: impl Into<Cow<'static, str>>,
388    ) -> InstrumentBuilder<'_, Histogram<f64>> {
389        InstrumentBuilder::new(self, name.into())
390    }
391
392    /// creates an instrument builder for recording a distribution of values.
393    pub fn u64_histogram(
394        &self,
395        name: impl Into<Cow<'static, str>>,
396    ) -> InstrumentBuilder<'_, Histogram<u64>> {
397        InstrumentBuilder::new(self, name.into())
398    }
399
400    /// Registers a callback to be called during the collection of a measurement
401    /// cycle.
402    ///
403    /// The instruments passed as arguments to be registered are the only
404    /// instruments that may observe values.
405    ///
406    /// If no instruments are passed, the callback will not be registered.
407    pub fn register_callback<F>(
408        &self,
409        instruments: &[Arc<dyn Any>],
410        callback: F,
411    ) -> Result<Box<dyn CallbackRegistration>>
412    where
413        F: Fn(&dyn Observer) + Send + Sync + 'static,
414    {
415        self.instrument_provider
416            .register_callback(instruments, Box::new(callback))
417    }
418}
419
420/// A token representing the unique registration of a callback for a set of
421/// instruments with a [Meter].
422pub trait CallbackRegistration: Send + Sync {
423    /// Removes the callback registration from its associated [Meter].
424    fn unregister(&mut self) -> Result<()>;
425}
426
427/// Records measurements for multiple instruments in a callback.
428pub trait Observer {
429    /// Records the f64 value with attributes for the observable.
430    fn observe_f64(&self, inst: &dyn AsyncInstrument<f64>, measurement: f64, attrs: &[KeyValue]);
431
432    /// Records the u64 value with attributes for the observable.
433    fn observe_u64(&self, inst: &dyn AsyncInstrument<u64>, measurement: u64, attrs: &[KeyValue]);
434
435    /// Records the i64 value with attributes for the observable.
436    fn observe_i64(&self, inst: &dyn AsyncInstrument<i64>, measurement: i64, attrs: &[KeyValue]);
437}
438
439impl fmt::Debug for Meter {
440    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
441        f.write_str("Meter")
442    }
443}