1use crate::metrics::{self, Meter, MeterProvider};
2use crate::KeyValue;
3use core::fmt;
4use once_cell::sync::Lazy;
5use std::{
6 borrow::Cow,
7 sync::{Arc, RwLock},
8};
910/// The global `MeterProvider` singleton.
11static GLOBAL_METER_PROVIDER: Lazy<RwLock<GlobalMeterProvider>> = Lazy::new(|| {
12 RwLock::new(GlobalMeterProvider::new(
13 metrics::noop::NoopMeterProvider::new(),
14 ))
15});
1617/// Allows a specific [MeterProvider] to be used generically by the
18/// [GlobalMeterProvider] by mirroring the interface and boxing the return types.
19pub trait ObjectSafeMeterProvider {
20/// Creates a versioned named meter instance that is a trait object through the underlying
21 /// [MeterProvider].
22fn versioned_meter_cow(
23&self,
24 name: Cow<'static, str>,
25 version: Option<Cow<'static, str>>,
26 schema_url: Option<Cow<'static, str>>,
27 attributes: Option<Vec<KeyValue>>,
28 ) -> Meter;
29}
3031impl<P> ObjectSafeMeterProvider for P
32where
33P: MeterProvider,
34{
35/// Return a versioned boxed tracer
36fn versioned_meter_cow(
37&self,
38 name: Cow<'static, str>,
39 version: Option<Cow<'static, str>>,
40 schema_url: Option<Cow<'static, str>>,
41 attributes: Option<Vec<KeyValue>>,
42 ) -> Meter {
43self.versioned_meter(name, version, schema_url, attributes)
44 }
45}
4647/// Represents the globally configured [`MeterProvider`] instance for this
48/// application.
49#[derive(Clone)]
50pub struct GlobalMeterProvider {
51 provider: Arc<dyn ObjectSafeMeterProvider + Send + Sync>,
52}
5354impl fmt::Debug for GlobalMeterProvider {
55fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
56 f.debug_struct("GlobalMeterProvider").finish()
57 }
58}
5960impl MeterProvider for GlobalMeterProvider {
61fn versioned_meter(
62&self,
63 name: impl Into<Cow<'static, str>>,
64 version: Option<impl Into<Cow<'static, str>>>,
65 schema_url: Option<impl Into<Cow<'static, str>>>,
66 attributes: Option<Vec<KeyValue>>,
67 ) -> Meter {
68self.provider.versioned_meter_cow(
69 name.into(),
70 version.map(Into::into),
71 schema_url.map(Into::into),
72 attributes,
73 )
74 }
75}
7677impl GlobalMeterProvider {
78/// Create a new global meter provider
79pub fn new<P>(provider: P) -> Self
80where
81P: MeterProvider + Send + Sync + 'static,
82 {
83 GlobalMeterProvider {
84 provider: Arc::new(provider),
85 }
86 }
87}
8889/// Sets the given [`MeterProvider`] instance as the current global meter
90/// provider.
91pub fn set_meter_provider<P>(new_provider: P)
92where
93P: metrics::MeterProvider + Send + Sync + 'static,
94{
95let mut global_provider = GLOBAL_METER_PROVIDER
96 .write()
97 .expect("GLOBAL_METER_PROVIDER RwLock poisoned");
98*global_provider = GlobalMeterProvider::new(new_provider);
99}
100101/// Returns an instance of the currently configured global [`MeterProvider`]
102/// through [`GlobalMeterProvider`].
103pub fn meter_provider() -> GlobalMeterProvider {
104 GLOBAL_METER_PROVIDER
105 .read()
106 .expect("GLOBAL_METER_PROVIDER RwLock poisoned")
107 .clone()
108}
109110/// Creates a named [`Meter`] via the configured [`GlobalMeterProvider`].
111///
112/// If the name is an empty string, the provider will use a default name.
113///
114/// This is a more convenient way of expressing `global::meter_provider().meter(name)`.
115pub fn meter(name: impl Into<Cow<'static, str>>) -> Meter {
116 meter_provider().meter(name.into())
117}
118119/// Creates a [`Meter`] with the name, version and schema url.
120///
121/// - name SHOULD uniquely identify the instrumentation scope, such as the instrumentation library (e.g. io.opentelemetry.contrib.mongodb), package, module or class name.
122/// - version specifies the version of the instrumentation scope if the scope has a version
123/// - schema url specifies the Schema URL that should be recorded in the emitted telemetry.
124///
125/// This is a convenient way of `global::meter_provider().versioned_meter(...)`
126///
127/// # Example
128///
129/// ```
130/// use opentelemetry::global::meter_with_version;
131/// use opentelemetry::KeyValue;
132///
133/// let meter = meter_with_version(
134/// "io.opentelemetry",
135/// Some("0.17"),
136/// Some("https://opentelemetry.io/schemas/1.2.0"),
137/// Some(vec![KeyValue::new("key", "value")]),
138/// );
139/// ```
140pub fn meter_with_version(
141 name: impl Into<Cow<'static, str>>,
142 version: Option<impl Into<Cow<'static, str>>>,
143 schema_url: Option<impl Into<Cow<'static, str>>>,
144 attributes: Option<Vec<KeyValue>>,
145) -> Meter {
146 meter_provider().versioned_meter(
147 name.into(),
148 version.map(Into::into),
149 schema_url.map(Into::into),
150 attributes,
151 )
152}