opentelemetry_spanprocessor_any/metrics/
meter.rs

1use std::fmt;
2use std::sync::Arc;
3
4use crate::sdk::InstrumentationLibrary;
5use crate::{
6    metrics::{
7        sdk_api, AsyncRunner, BatchObserver, BatchObserverResult, CounterBuilder, Descriptor,
8        Measurement, NumberKind, ObserverResult, Result, SumObserverBuilder, UpDownCounterBuilder,
9        UpDownSumObserverBuilder, ValueObserverBuilder, ValueRecorderBuilder,
10    },
11    Context, KeyValue,
12};
13
14/// Returns named meter instances
15pub trait MeterProvider: fmt::Debug {
16    /// Creates an implementation of the [`Meter`] interface. The
17    /// instrumentation name must be the name of the library providing
18    /// instrumentation. This name may be the same as the instrumented code only if
19    /// that code provides built-in instrumentation. If the instrumentation name is
20    /// empty, then a implementation defined default name will be used instead.
21    ///
22    fn meter(
23        &self,
24        instrumentation_name: &'static str,
25        instrumentation_version: Option<&'static str>,
26    ) -> Meter;
27}
28
29/// Meter is the OpenTelemetry metric API, based on a sdk-defined `MeterCore`
30/// implementation and the `Meter` library name.
31///
32/// # Instruments
33///
34/// | **Name** | Instrument kind | Function(argument) | Default aggregation | Notes |
35/// | ----------------------- | ----- | --------- | ------------- | --- |
36/// | **Counter**             | Synchronous adding monotonic | Add(increment) | Sum | Per-request, part of a monotonic sum |
37/// | **UpDownCounter**       | Synchronous adding | Add(increment) | Sum | Per-request, part of a non-monotonic sum |
38/// | **ValueRecorder**       | Synchronous  | Record(value) | [TBD issue 636](https://github.com/open-telemetry/opentelemetry-specification/issues/636)  | Per-request, any grouping measurement |
39/// | **SumObserver**         | Asynchronous adding monotonic | Observe(sum) | Sum | Per-interval, reporting a monotonic sum |
40/// | **UpDownSumObserver**   | Asynchronous adding | Observe(sum) | Sum | Per-interval, reporting a non-monotonic sum |
41/// | **ValueObserver**       | Asynchronous | Observe(value) | LastValue  | Per-interval, any grouping measurement |
42#[derive(Debug)]
43pub struct Meter {
44    instrumentation_library: InstrumentationLibrary,
45    core: Arc<dyn sdk_api::MeterCore + Send + Sync>,
46}
47
48impl Meter {
49    /// Create a new named meter from a sdk implemented core
50    pub fn new<T: Into<&'static str>>(
51        instrumentation_name: T,
52        instrumentation_version: Option<T>,
53        core: Arc<dyn sdk_api::MeterCore + Send + Sync>,
54    ) -> Self {
55        Meter {
56            instrumentation_library: InstrumentationLibrary::new(
57                instrumentation_name.into(),
58                instrumentation_version.map(Into::into),
59            ),
60            core,
61        }
62    }
63
64    pub(crate) fn instrumentation_library(&self) -> InstrumentationLibrary {
65        self.instrumentation_library.clone()
66    }
67
68    /// Creates a new integer `CounterBuilder` for `u64` values with the given name.
69    pub fn u64_counter<T>(&self, name: T) -> CounterBuilder<'_, u64>
70    where
71        T: Into<String>,
72    {
73        CounterBuilder::new(self, name.into(), NumberKind::U64)
74    }
75
76    /// Creates a new floating point `CounterBuilder` for `f64` values with the given name.
77    pub fn f64_counter<T>(&self, name: T) -> CounterBuilder<'_, f64>
78    where
79        T: Into<String>,
80    {
81        CounterBuilder::new(self, name.into(), NumberKind::F64)
82    }
83
84    /// Creates a new integer `UpDownCounterBuilder` for an `i64` up down counter with the given name.
85    pub fn i64_up_down_counter<T>(&self, name: T) -> UpDownCounterBuilder<'_, i64>
86    where
87        T: Into<String>,
88    {
89        UpDownCounterBuilder::new(self, name.into(), NumberKind::I64)
90    }
91
92    /// Creates a new floating point `UpDownCounterBuilder` for an `f64` up down counter with the given name.
93    pub fn f64_up_down_counter<T>(&self, name: T) -> UpDownCounterBuilder<'_, f64>
94    where
95        T: Into<String>,
96    {
97        UpDownCounterBuilder::new(self, name.into(), NumberKind::F64)
98    }
99
100    /// Creates a new `ValueRecorderBuilder` for `i64` values with the given name.
101    pub fn i64_value_recorder<T>(&self, name: T) -> ValueRecorderBuilder<'_, i64>
102    where
103        T: Into<String>,
104    {
105        ValueRecorderBuilder::new(self, name.into(), NumberKind::I64)
106    }
107
108    /// Creates a new `ValueRecorderBuilder` for `u64` values with the given name.
109    pub fn u64_value_recorder<T>(&self, name: T) -> ValueRecorderBuilder<'_, u64>
110    where
111        T: Into<String>,
112    {
113        ValueRecorderBuilder::new(self, name.into(), NumberKind::U64)
114    }
115
116    /// Creates a new `ValueRecorderBuilder` for `f64` values with the given name.
117    pub fn f64_value_recorder<T>(&self, name: T) -> ValueRecorderBuilder<'_, f64>
118    where
119        T: Into<String>,
120    {
121        ValueRecorderBuilder::new(self, name.into(), NumberKind::F64)
122    }
123
124    /// Creates a new integer `SumObserverBuilder` for `u64` values with the given
125    /// name and callback
126    pub fn u64_sum_observer<T, F>(&self, name: T, callback: F) -> SumObserverBuilder<'_, u64>
127    where
128        T: Into<String>,
129        F: Fn(ObserverResult<u64>) + Send + Sync + 'static,
130    {
131        SumObserverBuilder::new(
132            self,
133            name.into(),
134            Some(AsyncRunner::U64(Box::new(callback))),
135            NumberKind::U64,
136        )
137    }
138
139    /// Creates a new floating point `SumObserverBuilder` for `f64` values with the
140    /// given name and callback
141    pub fn f64_sum_observer<T, F>(&self, name: T, callback: F) -> SumObserverBuilder<'_, f64>
142    where
143        T: Into<String>,
144        F: Fn(ObserverResult<f64>) + Send + Sync + 'static,
145    {
146        SumObserverBuilder::new(
147            self,
148            name.into(),
149            Some(AsyncRunner::F64(Box::new(callback))),
150            NumberKind::F64,
151        )
152    }
153
154    /// Creates a new integer `UpDownSumObserverBuilder` for `i64` values with the
155    /// given name and callback.
156    pub fn i64_up_down_sum_observer<T, F>(
157        &self,
158        name: T,
159        callback: F,
160    ) -> UpDownSumObserverBuilder<'_, i64>
161    where
162        T: Into<String>,
163        F: Fn(ObserverResult<i64>) + Send + Sync + 'static,
164    {
165        UpDownSumObserverBuilder::new(
166            self,
167            name.into(),
168            Some(AsyncRunner::I64(Box::new(callback))),
169            NumberKind::I64,
170        )
171    }
172
173    /// Creates a new floating point `UpDownSumObserverBuilder` for `f64` values
174    /// with the given name and callback
175    pub fn f64_up_down_sum_observer<T, F>(
176        &self,
177        name: T,
178        callback: F,
179    ) -> UpDownSumObserverBuilder<'_, f64>
180    where
181        T: Into<String>,
182        F: Fn(ObserverResult<f64>) + Send + Sync + 'static,
183    {
184        UpDownSumObserverBuilder::new(
185            self,
186            name.into(),
187            Some(AsyncRunner::F64(Box::new(callback))),
188            NumberKind::F64,
189        )
190    }
191
192    /// Creates a new integer `ValueObserverBuilder` for `u64` values with the given
193    /// name and callback
194    pub fn u64_value_observer<T, F>(&self, name: T, callback: F) -> ValueObserverBuilder<'_, u64>
195    where
196        T: Into<String>,
197        F: Fn(ObserverResult<u64>) + Send + Sync + 'static,
198    {
199        ValueObserverBuilder::new(
200            self,
201            name.into(),
202            Some(AsyncRunner::U64(Box::new(callback))),
203            NumberKind::U64,
204        )
205    }
206
207    /// Creates a new integer `ValueObserverBuilder` for `i64` values with the given
208    /// name and callback
209    pub fn i64_value_observer<T, F>(&self, name: T, callback: F) -> ValueObserverBuilder<'_, i64>
210    where
211        T: Into<String>,
212        F: Fn(ObserverResult<i64>) + Send + Sync + 'static,
213    {
214        ValueObserverBuilder::new(
215            self,
216            name.into(),
217            Some(AsyncRunner::I64(Box::new(callback))),
218            NumberKind::I64,
219        )
220    }
221
222    /// Creates a new floating point `ValueObserverBuilder` for `f64` values with
223    /// the given name and callback
224    pub fn f64_value_observer<T, F>(&self, name: T, callback: F) -> ValueObserverBuilder<'_, f64>
225    where
226        T: Into<String>,
227        F: Fn(ObserverResult<f64>) + Send + Sync + 'static,
228    {
229        ValueObserverBuilder::new(
230            self,
231            name.into(),
232            Some(AsyncRunner::F64(Box::new(callback))),
233            NumberKind::F64,
234        )
235    }
236
237    /// Creates a new `BatchObserver` that supports making batches of observations
238    /// for multiple instruments or returns an error if instrument initialization
239    /// fails.
240    ///
241    /// # Examples
242    ///
243    /// ```
244    /// use opentelemetry::{global, metrics::BatchObserverResult, KeyValue};
245    ///
246    /// # fn init_observer() -> opentelemetry::metrics::Result<()> {
247    /// let meter = global::meter("test");
248    ///
249    /// meter.build_batch_observer(|batch| {
250    ///   let instrument = batch.u64_value_observer("test_instrument").try_init()?;
251    ///
252    ///   Ok(move |result: BatchObserverResult| {
253    ///     result.observe(&[KeyValue::new("my-key", "my-value")], &[instrument.observation(1)]);
254    ///   })
255    /// })?;
256    /// # Ok(())
257    /// # }
258    /// ```
259    pub fn build_batch_observer<B, F>(&self, builder: B) -> Result<()>
260    where
261        B: Fn(BatchObserver<'_>) -> Result<F>,
262        F: Fn(BatchObserverResult) + Send + Sync + 'static,
263    {
264        let observer = builder(BatchObserver::new(self))?;
265        self.core
266            .new_batch_observer(AsyncRunner::Batch(Box::new(observer)))
267    }
268
269    /// Creates a new `BatchObserver` that supports making batches of observations
270    /// for multiple instruments.
271    ///
272    /// # Panics
273    ///
274    /// Panics if instrument initialization or observer registration returns an
275    /// error.
276    ///
277    /// # Examples
278    ///
279    /// ```
280    /// use opentelemetry::{global, metrics::BatchObserverResult, KeyValue};
281    ///
282    /// let meter = global::meter("test");
283    ///
284    /// meter.batch_observer(|batch| {
285    ///   let instrument = batch.u64_value_observer("test_instrument").init();
286    ///
287    ///   move |result: BatchObserverResult| {
288    ///     result.observe(&[KeyValue::new("my-key", "my-value")], &[instrument.observation(1)]);
289    ///   }
290    /// });
291    /// ```
292    pub fn batch_observer<B, F>(&self, builder: B)
293    where
294        B: Fn(BatchObserver<'_>) -> F,
295        F: Fn(BatchObserverResult) + Send + Sync + 'static,
296    {
297        let observer = builder(BatchObserver::new(self));
298        self.core
299            .new_batch_observer(AsyncRunner::Batch(Box::new(observer)))
300            .unwrap()
301    }
302
303    /// Atomically record a batch of measurements.
304    pub fn record_batch<T: IntoIterator<Item = Measurement>>(
305        &self,
306        attributes: &[KeyValue],
307        measurements: T,
308    ) {
309        self.record_batch_with_context(&Context::current(), attributes, measurements)
310    }
311
312    /// Atomically record a batch of measurements with a given context
313    pub fn record_batch_with_context<T: IntoIterator<Item = Measurement>>(
314        &self,
315        cx: &Context,
316        attributes: &[KeyValue],
317        measurements: T,
318    ) {
319        self.core
320            .record_batch_with_context(cx, attributes, measurements.into_iter().collect())
321    }
322
323    pub(crate) fn new_sync_instrument(
324        &self,
325        descriptor: Descriptor,
326    ) -> Result<Arc<dyn sdk_api::SyncInstrumentCore>> {
327        self.core.new_sync_instrument(descriptor)
328    }
329
330    pub(crate) fn new_async_instrument(
331        &self,
332        descriptor: Descriptor,
333        runner: Option<AsyncRunner>,
334    ) -> Result<Arc<dyn sdk_api::AsyncInstrumentCore>> {
335        self.core.new_async_instrument(descriptor, runner)
336    }
337}