From c07700b0e6edc385286412c663c538f1526085db Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Tue, 28 Nov 2023 23:53:21 +0000 Subject: [PATCH 01/12] add synchronous gauge --- examples/metrics-basic/src/main.rs | 26 +++++-- opentelemetry-sdk/src/metrics/instrument.rs | 16 ++++- opentelemetry-sdk/src/metrics/meter.rs | 60 +++++++++++++++- opentelemetry-sdk/src/metrics/pipeline.rs | 14 ++-- opentelemetry-sdk/src/metrics/reader.rs | 2 + .../src/metrics/instruments/gauge.rs | 68 ++++++++++++++++++- opentelemetry/src/metrics/meter.rs | 32 ++++++++- opentelemetry/src/metrics/mod.rs | 32 ++++++++- opentelemetry/src/metrics/noop.rs | 8 ++- 9 files changed, 238 insertions(+), 20 deletions(-) diff --git a/examples/metrics-basic/src/main.rs b/examples/metrics-basic/src/main.rs index c3307d1f3a..4e6649a252 100644 --- a/examples/metrics-basic/src/main.rs +++ b/examples/metrics-basic/src/main.rs @@ -110,17 +110,33 @@ async fn main() -> Result<(), Box> { // Note that there is no ObservableHistogram instrument. - // Create a ObservableGauge instrument and register a callback that reports the measurement. + // Create a Gauge Instrument. + // Note that the Guage instrument is experimental, and can be changed/removed in the future releases. let gauge = meter - .f64_observable_gauge("my_gauge") + .f64_gauge("my_gauge") + .with_description("My gauge example description") + .with_unit(Unit::new("myunit")) + .init(); + gauge.record( + 1.0, + [ + KeyValue::new("mykey1", "myvalue1"), + KeyValue::new("mykey2", "myvalue2"), + ] + .as_ref(), + ); + + // Create a ObservableGauge instrument and register a callback that reports the measurement. + let observable_gauge = meter + .f64_observable_gauge("my_observable_gauge") .with_description("A gauge set to 1.0") .with_unit(Unit::new("myunit")) .init(); // Register a callback that reports the measurement. - meter.register_callback(&[gauge.as_any()], move |observer| { + meter.register_callback(&[observable_gauge.as_any()], move |observer| { observer.observe_f64( - &gauge, + &observable_gauge, 1.0, [ KeyValue::new("mykey1", "myvalue1"), @@ -130,8 +146,6 @@ async fn main() -> Result<(), Box> { ) })?; - // Note that Gauge only has a Observable version. - // Metrics are exported by default every 30 seconds when using stdout exporter, // however shutting down the MeterProvider here instantly flushes // the metrics, instead of waiting for the 30 sec interval. diff --git a/opentelemetry-sdk/src/metrics/instrument.rs b/opentelemetry-sdk/src/metrics/instrument.rs index 7971d47d3c..3ecae355b5 100644 --- a/opentelemetry-sdk/src/metrics/instrument.rs +++ b/opentelemetry-sdk/src/metrics/instrument.rs @@ -2,7 +2,8 @@ use std::{any::Any, borrow::Cow, collections::HashSet, hash::Hash, marker, sync: use opentelemetry::{ metrics::{ - AsyncInstrument, MetricsError, Result, SyncCounter, SyncHistogram, SyncUpDownCounter, Unit, + AsyncInstrument, MetricsError, Result, SyncCounter, SyncGauge, SyncHistogram, + SyncUpDownCounter, Unit, }, Key, KeyValue, }; @@ -33,6 +34,11 @@ pub enum InstrumentKind { /// A group of instruments that record increasing and decreasing values in an /// asynchronous callback. ObservableUpDownCounter, + + /// a group of instruments that record current value synchronously with + /// the code path they are measuring. + Gauge, + /// /// a group of instruments that record current values in an asynchronous callback. ObservableGauge, } @@ -268,6 +274,14 @@ impl SyncUpDownCounter for ResolvedMeasures { } } +impl SyncGauge for ResolvedMeasures { + fn record(&self, val: T, attrs: &[KeyValue]) { + for measure in &self.measures { + measure.call(val, AttributeSet::from(attrs)) + } + } +} + impl SyncHistogram for ResolvedMeasures { fn record(&self, val: T, attrs: &[KeyValue]) { for measure in &self.measures { diff --git a/opentelemetry-sdk/src/metrics/meter.rs b/opentelemetry-sdk/src/metrics/meter.rs index 5eaeba7745..c801adcb0a 100644 --- a/opentelemetry-sdk/src/metrics/meter.rs +++ b/opentelemetry-sdk/src/metrics/meter.rs @@ -5,9 +5,9 @@ use opentelemetry::{ global, metrics::{ noop::{NoopAsyncInstrument, NoopRegistration}, - AsyncInstrument, Callback, CallbackRegistration, Counter, Histogram, InstrumentProvider, - MetricsError, ObservableCounter, ObservableGauge, ObservableUpDownCounter, - Observer as ApiObserver, Result, Unit, UpDownCounter, + AsyncInstrument, Callback, CallbackRegistration, Counter, Gauge, Histogram, + InstrumentProvider, MetricsError, ObservableCounter, ObservableGauge, + ObservableUpDownCounter, Observer as ApiObserver, Result, Unit, UpDownCounter, }, KeyValue, }; @@ -299,6 +299,57 @@ impl InstrumentProvider for SdkMeter { Ok(ObservableUpDownCounter::new(observable)) } + fn u64_gauge( + &self, + name: Cow<'static, str>, + description: Option>, + unit: Option, + ) -> Result> { + validate_instrument_config(name.as_ref(), unit.as_ref(), self.validation_policy)?; + let p = InstrumentResolver::new(self, &self.u64_resolver); + p.lookup( + InstrumentKind::Gauge, + name, + description, + unit.unwrap_or_default(), + ) + .map(|i| Gauge::new(Arc::new(i))) + } + + fn f64_gauge( + &self, + name: Cow<'static, str>, + description: Option>, + unit: Option, + ) -> Result> { + validate_instrument_config(name.as_ref(), unit.as_ref(), self.validation_policy)?; + let p = InstrumentResolver::new(self, &self.f64_resolver); + p.lookup( + InstrumentKind::Gauge, + name, + description, + unit.unwrap_or_default(), + ) + .map(|i| Gauge::new(Arc::new(i))) + } + + fn i64_gauge( + &self, + name: Cow<'static, str>, + description: Option>, + unit: Option, + ) -> Result> { + validate_instrument_config(name.as_ref(), unit.as_ref(), self.validation_policy)?; + let p = InstrumentResolver::new(self, &self.i64_resolver); + p.lookup( + InstrumentKind::Gauge, + name, + description, + unit.unwrap_or_default(), + ) + .map(|i| Gauge::new(Arc::new(i))) + } + fn u64_observable_gauge( &self, name: Cow<'static, str>, @@ -784,6 +835,9 @@ mod tests { .f64_observable_up_down_counter(name.into(), None, None, Vec::new()) .map(|_| ()), ); + assert(meter.u64_gauge(name.into(), None, None).map(|_| ())); + assert(meter.f64_gauge(name.into(), None, None).map(|_| ())); + assert(meter.i64_gauge(name.into(), None, None).map(|_| ())); assert( meter .u64_observable_gauge(name.into(), None, None, Vec::new()) diff --git a/opentelemetry-sdk/src/metrics/pipeline.rs b/opentelemetry-sdk/src/metrics/pipeline.rs index 6ebd7c9e05..be0dde9736 100644 --- a/opentelemetry-sdk/src/metrics/pipeline.rs +++ b/opentelemetry-sdk/src/metrics/pipeline.rs @@ -536,6 +536,7 @@ fn aggregate_fn>( /// | Histogram | ✓ | | ✓ | ✓ | ✓ | /// | Observable Counter | ✓ | | ✓ | ✓ | ✓ | /// | Observable UpDownCounter | ✓ | | ✓ | ✓ | ✓ | +/// | Gauge | ✓ | ✓ | | ✓ | ✓ | /// | Observable Gauge | ✓ | ✓ | | ✓ | ✓ | fn is_aggregator_compatible(kind: &InstrumentKind, agg: &aggregation::Aggregation) -> Result<()> { use aggregation::Aggregation; @@ -547,6 +548,7 @@ fn is_aggregator_compatible(kind: &InstrumentKind, agg: &aggregation::Aggregatio kind, InstrumentKind::Counter | InstrumentKind::UpDownCounter + | InstrumentKind::Gauge | InstrumentKind::Histogram | InstrumentKind::ObservableCounter | InstrumentKind::ObservableUpDownCounter @@ -571,12 +573,14 @@ fn is_aggregator_compatible(kind: &InstrumentKind, agg: &aggregation::Aggregatio } } Aggregation::LastValue => { - if kind == &InstrumentKind::ObservableGauge { - return Ok(()); + match kind { + InstrumentKind::Gauge | InstrumentKind::ObservableGauge => Ok(()), + _ => { + // TODO: review need for aggregation check after + // https://github.com/open-telemetry/opentelemetry-specification/issues/2710 + Err(MetricsError::Other("incompatible aggregation".into())) + } } - // TODO: review need for aggregation check after - // https://github.com/open-telemetry/opentelemetry-specification/issues/2710 - Err(MetricsError::Other("incompatible aggregation".into())) } Aggregation::Drop => Ok(()), } diff --git a/opentelemetry-sdk/src/metrics/reader.rs b/opentelemetry-sdk/src/metrics/reader.rs index 11cd9ae060..f53e507dc1 100644 --- a/opentelemetry-sdk/src/metrics/reader.rs +++ b/opentelemetry-sdk/src/metrics/reader.rs @@ -121,6 +121,7 @@ where /// * Observable Counter ⇨ Sum /// * UpDownCounter ⇨ Sum /// * Observable UpDownCounter ⇨ Sum +/// * Gauge ⇨ LastValue /// * Observable Gauge ⇨ LastValue /// * Histogram ⇨ ExplicitBucketHistogram /// @@ -144,6 +145,7 @@ impl AggregationSelector for DefaultAggregationSelector { | InstrumentKind::UpDownCounter | InstrumentKind::ObservableCounter | InstrumentKind::ObservableUpDownCounter => Aggregation::Sum, + InstrumentKind::Gauge => Aggregation::LastValue, InstrumentKind::ObservableGauge => Aggregation::LastValue, InstrumentKind::Histogram => Aggregation::ExplicitBucketHistogram { boundaries: vec![ diff --git a/opentelemetry/src/metrics/instruments/gauge.rs b/opentelemetry/src/metrics/instruments/gauge.rs index b9f082d83a..d22f9296e9 100644 --- a/opentelemetry/src/metrics/instruments/gauge.rs +++ b/opentelemetry/src/metrics/instruments/gauge.rs @@ -1,12 +1,76 @@ use crate::{ - metrics::{AsyncInstrument, AsyncInstrumentBuilder, MetricsError}, + metrics::{AsyncInstrument, AsyncInstrumentBuilder, InstrumentBuilder, MetricsError}, KeyValue, }; use core::fmt; use std::sync::Arc; use std::{any::Any, convert::TryFrom}; -/// An instrument that records independent readings. +/// An SDK implemented instrument that records independent values +pub trait SyncGauge { + /// Records an increment to the counter. + fn record(&self, value: T, attributes: &[KeyValue]); +} + +/// An instrument that records independent values +#[derive(Clone)] +pub struct Gauge(Arc + Send + Sync>); + +impl fmt::Debug for Gauge +where + T: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_fmt(format_args!("Gauge<{}>", std::any::type_name::())) + } +} + +impl Gauge { + /// Create a new counter. + pub fn new(inner: Arc + Send + Sync>) -> Self { + Gauge(inner) + } + + /// Records an increment to the counter. + pub fn record(&self, value: T, attributes: &[KeyValue]) { + self.0.record(value, attributes) + } +} + +impl TryFrom>> for Gauge { + type Error = MetricsError; + + fn try_from(builder: InstrumentBuilder<'_, Gauge>) -> Result { + builder + .meter + .instrument_provider + .u64_gauge(builder.name, builder.description, builder.unit) + } +} + +impl TryFrom>> for Gauge { + type Error = MetricsError; + + fn try_from(builder: InstrumentBuilder<'_, Gauge>) -> Result { + builder + .meter + .instrument_provider + .f64_gauge(builder.name, builder.description, builder.unit) + } +} + +impl TryFrom>> for Gauge { + type Error = MetricsError; + + fn try_from(builder: InstrumentBuilder<'_, Gauge>) -> Result { + builder + .meter + .instrument_provider + .i64_gauge(builder.name, builder.description, builder.unit) + } +} + +/// An async instrument that records independent readings. #[derive(Clone)] pub struct ObservableGauge(Arc>); diff --git a/opentelemetry/src/metrics/meter.rs b/opentelemetry/src/metrics/meter.rs index a66a77e55c..0563661e52 100644 --- a/opentelemetry/src/metrics/meter.rs +++ b/opentelemetry/src/metrics/meter.rs @@ -4,7 +4,7 @@ use std::borrow::Cow; use std::sync::Arc; use crate::metrics::{ - AsyncInstrumentBuilder, Counter, Histogram, InstrumentBuilder, InstrumentProvider, + AsyncInstrumentBuilder, Counter, Gauge, Histogram, InstrumentBuilder, InstrumentProvider, ObservableCounter, ObservableGauge, ObservableUpDownCounter, Result, UpDownCounter, }; use crate::KeyValue; @@ -333,6 +333,36 @@ impl Meter { AsyncInstrumentBuilder::new(self, name.into()) } + /// # Experimental + /// This method is experimental and can be changed/removed in future releases. + /// creates an instrument builder for recording independent values. + pub fn u64_gauge( + &self, + name: impl Into>, + ) -> InstrumentBuilder<'_, Gauge> { + InstrumentBuilder::new(self, name.into()) + } + + /// # Experimental + /// This method is experimental and can be changed/removed in future releases. + /// creates an instrument builder for recording independent values. + pub fn f64_gauge( + &self, + name: impl Into>, + ) -> InstrumentBuilder<'_, Gauge> { + InstrumentBuilder::new(self, name.into()) + } + + /// # Experimental + /// This method is experimental and can be changed/removed in future releases. + /// creates an instrument builder for recording indenpendent values. + pub fn i64_gauge( + &self, + name: impl Into>, + ) -> InstrumentBuilder<'_, Gauge> { + InstrumentBuilder::new(self, name.into()) + } + /// creates an instrument builder for recording the current value via callback. pub fn u64_observable_gauge( &self, diff --git a/opentelemetry/src/metrics/mod.rs b/opentelemetry/src/metrics/mod.rs index 4241363411..34ed16fa39 100644 --- a/opentelemetry/src/metrics/mod.rs +++ b/opentelemetry/src/metrics/mod.rs @@ -13,7 +13,7 @@ pub mod noop; use crate::ExportError; pub use instruments::{ counter::{Counter, ObservableCounter, SyncCounter}, - gauge::ObservableGauge, + gauge::{Gauge, ObservableGauge, SyncGauge}, histogram::{Histogram, SyncHistogram}, up_down_counter::{ObservableUpDownCounter, SyncUpDownCounter, UpDownCounter}, AsyncInstrument, AsyncInstrumentBuilder, Callback, InstrumentBuilder, @@ -179,6 +179,36 @@ pub trait InstrumentProvider { ))) } + /// creates an instrument for recording independent values. + fn u64_gauge( + &self, + _name: Cow<'static, str>, + _description: Option>, + _unit: Option, + ) -> Result> { + Ok(Gauge::new(Arc::new(noop::NoopSyncInstrument::new()))) + } + + /// creates an instrument for recording independent values. + fn f64_gauge( + &self, + _name: Cow<'static, str>, + _description: Option>, + _unit: Option, + ) -> Result> { + Ok(Gauge::new(Arc::new(noop::NoopSyncInstrument::new()))) + } + + /// creates an instrument for recording independent values. + fn i64_gauge( + &self, + _name: Cow<'static, str>, + _description: Option>, + _unit: Option, + ) -> Result> { + Ok(Gauge::new(Arc::new(noop::NoopSyncInstrument::new()))) + } + /// creates an instrument for recording the current value via callback. fn u64_observable_gauge( &self, diff --git a/opentelemetry/src/metrics/noop.rs b/opentelemetry/src/metrics/noop.rs index 361bed29e7..adf4b03da3 100644 --- a/opentelemetry/src/metrics/noop.rs +++ b/opentelemetry/src/metrics/noop.rs @@ -6,7 +6,7 @@ use crate::{ metrics::{ AsyncInstrument, CallbackRegistration, InstrumentProvider, Meter, MeterProvider, Observer, - Result, SyncCounter, SyncHistogram, SyncUpDownCounter, + Result, SyncCounter, SyncGauge, SyncHistogram, SyncUpDownCounter, }, KeyValue, }; @@ -110,6 +110,12 @@ impl SyncHistogram for NoopSyncInstrument { } } +impl SyncGauge for NoopSyncInstrument { + fn record(&self, _value: T, _attributes: &[KeyValue]) { + // Ignored + } +} + /// A no-op async instrument. #[derive(Debug, Default)] pub struct NoopAsyncInstrument { From 85602352f8222ad2ddafb7711002c7336c4cd3e3 Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Wed, 29 Nov 2023 00:15:55 +0000 Subject: [PATCH 02/12] add experimental feature --- examples/metrics-basic/Cargo.toml | 2 +- examples/metrics-basic/src/main.rs | 6 ++++-- opentelemetry/Cargo.toml | 1 + opentelemetry/src/metrics/meter.rs | 7 ++++++- 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/examples/metrics-basic/Cargo.toml b/examples/metrics-basic/Cargo.toml index 1e33cdfd7e..2162a0d2b1 100644 --- a/examples/metrics-basic/Cargo.toml +++ b/examples/metrics-basic/Cargo.toml @@ -6,7 +6,7 @@ license = "Apache-2.0" publish = false [dependencies] -opentelemetry = { path = "../../opentelemetry", features = ["metrics"] } +opentelemetry = { path = "../../opentelemetry", features = ["metrics", "sync-gauge-experimental"] } opentelemetry_sdk = { path = "../../opentelemetry-sdk", features = ["metrics", "rt-tokio"] } opentelemetry-stdout = { path = "../../opentelemetry-stdout", features = ["metrics"]} tokio = { version = "1.0", features = ["full"] } diff --git a/examples/metrics-basic/src/main.rs b/examples/metrics-basic/src/main.rs index 4e6649a252..cf26a81c97 100644 --- a/examples/metrics-basic/src/main.rs +++ b/examples/metrics-basic/src/main.rs @@ -112,11 +112,13 @@ async fn main() -> Result<(), Box> { // Create a Gauge Instrument. // Note that the Guage instrument is experimental, and can be changed/removed in the future releases. + #[cfg(feature = "sync-gauge-experimental")] let gauge = meter .f64_gauge("my_gauge") - .with_description("My gauge example description") + .with_description("A gauge set to 1.0") .with_unit(Unit::new("myunit")) .init(); + #[cfg(feature = "sync-gauge-experimental")] gauge.record( 1.0, [ @@ -129,7 +131,7 @@ async fn main() -> Result<(), Box> { // Create a ObservableGauge instrument and register a callback that reports the measurement. let observable_gauge = meter .f64_observable_gauge("my_observable_gauge") - .with_description("A gauge set to 1.0") + .with_description("An observable gauge set to 1.0") .with_unit(Unit::new("myunit")) .init(); diff --git a/opentelemetry/Cargo.toml b/opentelemetry/Cargo.toml index 957d2d6a49..371bd68dc4 100644 --- a/opentelemetry/Cargo.toml +++ b/opentelemetry/Cargo.toml @@ -38,6 +38,7 @@ metrics = [] testing = ["trace", "metrics"] logs = [] logs_level_enabled = ["logs"] +sync-gauge-experimental = [] [dev-dependencies] opentelemetry_sdk = { path = "../opentelemetry-sdk" } # for documentation tests diff --git a/opentelemetry/src/metrics/meter.rs b/opentelemetry/src/metrics/meter.rs index 0563661e52..76c5b60744 100644 --- a/opentelemetry/src/metrics/meter.rs +++ b/opentelemetry/src/metrics/meter.rs @@ -3,8 +3,10 @@ use std::any::Any; use std::borrow::Cow; use std::sync::Arc; +#[cfg(feature = "sync-gauge-experimental")] +use crate::metrics::Gauge; use crate::metrics::{ - AsyncInstrumentBuilder, Counter, Gauge, Histogram, InstrumentBuilder, InstrumentProvider, + AsyncInstrumentBuilder, Counter, Histogram, InstrumentBuilder, InstrumentProvider, ObservableCounter, ObservableGauge, ObservableUpDownCounter, Result, UpDownCounter, }; use crate::KeyValue; @@ -336,6 +338,7 @@ impl Meter { /// # Experimental /// This method is experimental and can be changed/removed in future releases. /// creates an instrument builder for recording independent values. + #[cfg(feature = "sync-gauge-experimental")] pub fn u64_gauge( &self, name: impl Into>, @@ -346,6 +349,7 @@ impl Meter { /// # Experimental /// This method is experimental and can be changed/removed in future releases. /// creates an instrument builder for recording independent values. + #[cfg(feature = "sync-gauge-experimental")] pub fn f64_gauge( &self, name: impl Into>, @@ -356,6 +360,7 @@ impl Meter { /// # Experimental /// This method is experimental and can be changed/removed in future releases. /// creates an instrument builder for recording indenpendent values. + #[cfg(feature = "sync-gauge-experimental")] pub fn i64_gauge( &self, name: impl Into>, From e3f5903a08d43d1825cf1c7bfcbb3f134cc1af05 Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Wed, 29 Nov 2023 00:37:57 +0000 Subject: [PATCH 03/12] fix comments --- examples/metrics-basic/src/main.rs | 2 +- opentelemetry/src/metrics/instruments/gauge.rs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/metrics-basic/src/main.rs b/examples/metrics-basic/src/main.rs index cf26a81c97..7085b37202 100644 --- a/examples/metrics-basic/src/main.rs +++ b/examples/metrics-basic/src/main.rs @@ -111,7 +111,7 @@ async fn main() -> Result<(), Box> { // Note that there is no ObservableHistogram instrument. // Create a Gauge Instrument. - // Note that the Guage instrument is experimental, and can be changed/removed in the future releases. + // Note that the Gauge instrument is experimental, and can be changed/removed in the future releases. #[cfg(feature = "sync-gauge-experimental")] let gauge = meter .f64_gauge("my_gauge") diff --git a/opentelemetry/src/metrics/instruments/gauge.rs b/opentelemetry/src/metrics/instruments/gauge.rs index d22f9296e9..ab9fb2e05d 100644 --- a/opentelemetry/src/metrics/instruments/gauge.rs +++ b/opentelemetry/src/metrics/instruments/gauge.rs @@ -8,7 +8,7 @@ use std::{any::Any, convert::TryFrom}; /// An SDK implemented instrument that records independent values pub trait SyncGauge { - /// Records an increment to the counter. + /// Records an independent value. fn record(&self, value: T, attributes: &[KeyValue]); } @@ -26,12 +26,12 @@ where } impl Gauge { - /// Create a new counter. + /// Create a new gauge. pub fn new(inner: Arc + Send + Sync>) -> Self { Gauge(inner) } - /// Records an increment to the counter. + /// Records an independent value. pub fn record(&self, value: T, attributes: &[KeyValue]) { self.0.record(value, attributes) } From 7d43e66227a417612093213bd1ea80f4b13ac3c4 Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Wed, 29 Nov 2023 00:52:52 +0000 Subject: [PATCH 04/12] enable gauge in metrics example --- examples/metrics-basic/Cargo.toml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/examples/metrics-basic/Cargo.toml b/examples/metrics-basic/Cargo.toml index 2162a0d2b1..0653073c1b 100644 --- a/examples/metrics-basic/Cargo.toml +++ b/examples/metrics-basic/Cargo.toml @@ -10,4 +10,8 @@ opentelemetry = { path = "../../opentelemetry", features = ["metrics", "sync-gau opentelemetry_sdk = { path = "../../opentelemetry-sdk", features = ["metrics", "rt-tokio"] } opentelemetry-stdout = { path = "../../opentelemetry-stdout", features = ["metrics"]} tokio = { version = "1.0", features = ["full"] } -serde_json = {version = "1.0"} \ No newline at end of file +serde_json = {version = "1.0"} + +[features] +default = ["sync-gauge-experimental"] +sync-gauge-experimental = ["opentelemetry/sync-gauge-experimental"] \ No newline at end of file From aa1a2a5d4c477adb09b45e9b151718af8b05bcb2 Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Thu, 30 Nov 2023 22:09:29 +0000 Subject: [PATCH 05/12] use otel_unstable cfg --- examples/metrics-basic/Cargo.toml | 6 +----- examples/metrics-basic/src/main.rs | 32 ++++++++++++++++-------------- opentelemetry/Cargo.toml | 2 +- opentelemetry/src/metrics/meter.rs | 6 +++--- 4 files changed, 22 insertions(+), 24 deletions(-) diff --git a/examples/metrics-basic/Cargo.toml b/examples/metrics-basic/Cargo.toml index 0653073c1b..61d9624c36 100644 --- a/examples/metrics-basic/Cargo.toml +++ b/examples/metrics-basic/Cargo.toml @@ -6,12 +6,8 @@ license = "Apache-2.0" publish = false [dependencies] -opentelemetry = { path = "../../opentelemetry", features = ["metrics", "sync-gauge-experimental"] } +opentelemetry = { path = "../../opentelemetry", features = ["metrics"] } opentelemetry_sdk = { path = "../../opentelemetry-sdk", features = ["metrics", "rt-tokio"] } opentelemetry-stdout = { path = "../../opentelemetry-stdout", features = ["metrics"]} tokio = { version = "1.0", features = ["full"] } serde_json = {version = "1.0"} - -[features] -default = ["sync-gauge-experimental"] -sync-gauge-experimental = ["opentelemetry/sync-gauge-experimental"] \ No newline at end of file diff --git a/examples/metrics-basic/src/main.rs b/examples/metrics-basic/src/main.rs index 7085b37202..25c07af098 100644 --- a/examples/metrics-basic/src/main.rs +++ b/examples/metrics-basic/src/main.rs @@ -112,21 +112,23 @@ async fn main() -> Result<(), Box> { // Create a Gauge Instrument. // Note that the Gauge instrument is experimental, and can be changed/removed in the future releases. - #[cfg(feature = "sync-gauge-experimental")] - let gauge = meter - .f64_gauge("my_gauge") - .with_description("A gauge set to 1.0") - .with_unit(Unit::new("myunit")) - .init(); - #[cfg(feature = "sync-gauge-experimental")] - gauge.record( - 1.0, - [ - KeyValue::new("mykey1", "myvalue1"), - KeyValue::new("mykey2", "myvalue2"), - ] - .as_ref(), - ); + #[cfg(otel_unstable)] + { + let gauge = meter + .f64_gauge("my_gauge") + .with_description("A gauge set to 1.0") + .with_unit(Unit::new("myunit")) + .init(); + + gauge.record( + 1.0, + [ + KeyValue::new("mykey1", "myvalue1"), + KeyValue::new("mykey2", "myvalue2"), + ] + .as_ref(), + ); + } // Create a ObservableGauge instrument and register a callback that reports the measurement. let observable_gauge = meter diff --git a/opentelemetry/Cargo.toml b/opentelemetry/Cargo.toml index 371bd68dc4..98ae488386 100644 --- a/opentelemetry/Cargo.toml +++ b/opentelemetry/Cargo.toml @@ -38,7 +38,7 @@ metrics = [] testing = ["trace", "metrics"] logs = [] logs_level_enabled = ["logs"] -sync-gauge-experimental = [] +unstable = [] [dev-dependencies] opentelemetry_sdk = { path = "../opentelemetry-sdk" } # for documentation tests diff --git a/opentelemetry/src/metrics/meter.rs b/opentelemetry/src/metrics/meter.rs index 76c5b60744..534acec9ae 100644 --- a/opentelemetry/src/metrics/meter.rs +++ b/opentelemetry/src/metrics/meter.rs @@ -3,7 +3,7 @@ use std::any::Any; use std::borrow::Cow; use std::sync::Arc; -#[cfg(feature = "sync-gauge-experimental")] +#[cfg(otel_unstable)] use crate::metrics::Gauge; use crate::metrics::{ AsyncInstrumentBuilder, Counter, Histogram, InstrumentBuilder, InstrumentProvider, @@ -338,7 +338,7 @@ impl Meter { /// # Experimental /// This method is experimental and can be changed/removed in future releases. /// creates an instrument builder for recording independent values. - #[cfg(feature = "sync-gauge-experimental")] + #[cfg(otel_unstable)] pub fn u64_gauge( &self, name: impl Into>, @@ -349,7 +349,7 @@ impl Meter { /// # Experimental /// This method is experimental and can be changed/removed in future releases. /// creates an instrument builder for recording independent values. - #[cfg(feature = "sync-gauge-experimental")] + #[cfg(otel_unstable)] pub fn f64_gauge( &self, name: impl Into>, From 271111f07737f1e84eb89dd2e38dbd0a9c770407 Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Thu, 30 Nov 2023 22:26:31 +0000 Subject: [PATCH 06/12] update contributing.md --- CONTRIBUTING.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e831d0df42..5f7df4d5c5 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -137,6 +137,19 @@ OpenTelemetry supports multiple ways to configure the API, SDK and other compone - Environment variables - Compiling time configurations provided in the source code +### Experimental/Unstable features: + +Use `otel_unstable` flag for implementation of specification with [experimental](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.27.0/specification/document-status.md) status. This approach ensures clear demarcation and safe integration of new or evolving features. Utilize the following structure: + +```rust +#[cfg(otel_unstable)] +{ + // Your feature implementation +} +``` + +It's important to regularly review and remove the `otel_unstable` flag from the code once the feature becomes stable. This cleanup process is crucial to maintain the overall code quality and to ensure that stable features are accurately reflected in the main build. + ## Style Guide - Run `cargo clippy --all` - this will catch common mistakes and improve From 2c0f989d42832a4c3ca54552a518d7bbf71c4280 Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Fri, 1 Dec 2023 00:26:00 +0000 Subject: [PATCH 07/12] changelog --- opentelemetry-sdk/CHANGELOG.md | 5 +++++ opentelemetry/CHANGELOG.md | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/opentelemetry-sdk/CHANGELOG.md b/opentelemetry-sdk/CHANGELOG.md index 1b5e0b76f9..8f6d321486 100644 --- a/opentelemetry-sdk/CHANGELOG.md +++ b/opentelemetry-sdk/CHANGELOG.md @@ -2,6 +2,11 @@ ## vNext +### Added + + +- [#1410](https://github.com/open-telemetry/opentelemetry-rust/pull/1410) Add experimental synchronous gauge + ### Changed - **Breaking** diff --git a/opentelemetry/CHANGELOG.md b/opentelemetry/CHANGELOG.md index 77c5b52a93..1696182932 100644 --- a/opentelemetry/CHANGELOG.md +++ b/opentelemetry/CHANGELOG.md @@ -2,6 +2,10 @@ ## vNext +### Added + +- [#1410](https://github.com/open-telemetry/opentelemetry-rust/pull/1410) Add experimental synchronous gauge + ### Changed - Modified `AnyValue.Map` to be backed by `HashMap` instead of custom `OrderMap`, From ac7971d588d1716d3f4c5166d8778bc36136d3a5 Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Fri, 1 Dec 2023 00:32:57 +0000 Subject: [PATCH 08/12] changelog --- opentelemetry-sdk/CHANGELOG.md | 1 - opentelemetry/CHANGELOG.md | 4 +++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/opentelemetry-sdk/CHANGELOG.md b/opentelemetry-sdk/CHANGELOG.md index 8f6d321486..ddb2315b70 100644 --- a/opentelemetry-sdk/CHANGELOG.md +++ b/opentelemetry-sdk/CHANGELOG.md @@ -4,7 +4,6 @@ ### Added - - [#1410](https://github.com/open-telemetry/opentelemetry-rust/pull/1410) Add experimental synchronous gauge ### Changed diff --git a/opentelemetry/CHANGELOG.md b/opentelemetry/CHANGELOG.md index 1696182932..75fed06406 100644 --- a/opentelemetry/CHANGELOG.md +++ b/opentelemetry/CHANGELOG.md @@ -4,7 +4,9 @@ ### Added -- [#1410](https://github.com/open-telemetry/opentelemetry-rust/pull/1410) Add experimental synchronous gauge +- [#1410](https://github.com/open-telemetry/opentelemetry-rust/pull/1410) Add experimental synchronous gauge. + +- [#1410](https://github.com/open-telemetry/opentelemetry-rust/pull/1410) Guidelines to add new unstable/experimental features. ### Changed From bbb16134f2bdcde7db7507de93666a6e0214717a Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Fri, 1 Dec 2023 18:27:18 +0000 Subject: [PATCH 09/12] update changelog --- opentelemetry/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opentelemetry/CHANGELOG.md b/opentelemetry/CHANGELOG.md index 75fed06406..d9115489fd 100644 --- a/opentelemetry/CHANGELOG.md +++ b/opentelemetry/CHANGELOG.md @@ -4,7 +4,7 @@ ### Added -- [#1410](https://github.com/open-telemetry/opentelemetry-rust/pull/1410) Add experimental synchronous gauge. +- [#1410](https://github.com/open-telemetry/opentelemetry-rust/pull/1410) Add experimental synchronous gauge. This is behind the conditional flag, and can be enabled by setting the environment variable RUSTFLAGS="--cfg=otel_unstable". - [#1410](https://github.com/open-telemetry/opentelemetry-rust/pull/1410) Guidelines to add new unstable/experimental features. From 251736c95d2b91b3b2f8d96cf123fcd5e4217153 Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Sat, 2 Dec 2023 00:26:46 +0000 Subject: [PATCH 10/12] switch to feature flag --- CONTRIBUTING.md | 14 +++++++++++--- examples/metrics-basic/Cargo.toml | 6 +++++- examples/metrics-basic/src/main.rs | 2 +- opentelemetry/CHANGELOG.md | 2 +- opentelemetry/Cargo.toml | 2 +- opentelemetry/src/metrics/meter.rs | 8 ++++---- 6 files changed, 23 insertions(+), 11 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5f7df4d5c5..4873692c37 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -139,17 +139,25 @@ OpenTelemetry supports multiple ways to configure the API, SDK and other compone ### Experimental/Unstable features: -Use `otel_unstable` flag for implementation of specification with [experimental](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.27.0/specification/document-status.md) status. This approach ensures clear demarcation and safe integration of new or evolving features. Utilize the following structure: +Use `otel_unstable` feature flag for implementation of specification with [experimental](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.27.0/specification/document-status.md) status. This approach ensures clear demarcation and safe integration of new or evolving features. Utilize the following structure: ```rust -#[cfg(otel_unstable)] +#[cfg(feature = "otel_unstable")] { // Your feature implementation } ``` - It's important to regularly review and remove the `otel_unstable` flag from the code once the feature becomes stable. This cleanup process is crucial to maintain the overall code quality and to ensure that stable features are accurately reflected in the main build. +### Optional features: + +The potential features include: + +- Stable and non-experimental features that are included in the specification to minimize compilation size. These could be separate feature flags for signals (like `logs`, `traces`, `metrics`) and runtimes (`rt-tokio`, `rt-tokio-current-thread`, `rt-async-std`). +- Stable and non-experimental features, although not part of the specification, are crucial for enhancing the tracing/log crate's functionality or boosting performance. Example: `logs_level_enabled`. + +All such features should adhere to naming convention `_` + ## Style Guide - Run `cargo clippy --all` - this will catch common mistakes and improve diff --git a/examples/metrics-basic/Cargo.toml b/examples/metrics-basic/Cargo.toml index 61d9624c36..d505b8cbd5 100644 --- a/examples/metrics-basic/Cargo.toml +++ b/examples/metrics-basic/Cargo.toml @@ -6,8 +6,12 @@ license = "Apache-2.0" publish = false [dependencies] -opentelemetry = { path = "../../opentelemetry", features = ["metrics"] } +opentelemetry = { path = "../../opentelemetry", features = ["metrics", "otel_unstable"] } opentelemetry_sdk = { path = "../../opentelemetry-sdk", features = ["metrics", "rt-tokio"] } opentelemetry-stdout = { path = "../../opentelemetry-stdout", features = ["metrics"]} tokio = { version = "1.0", features = ["full"] } serde_json = {version = "1.0"} + +[features] +default = ["otel_unstable"] +otel_unstable = ["opentelemetry/otel_unstable"] diff --git a/examples/metrics-basic/src/main.rs b/examples/metrics-basic/src/main.rs index 25c07af098..78dda47cad 100644 --- a/examples/metrics-basic/src/main.rs +++ b/examples/metrics-basic/src/main.rs @@ -112,7 +112,7 @@ async fn main() -> Result<(), Box> { // Create a Gauge Instrument. // Note that the Gauge instrument is experimental, and can be changed/removed in the future releases. - #[cfg(otel_unstable)] + #[cfg(feature = "otel_unstable")] { let gauge = meter .f64_gauge("my_gauge") diff --git a/opentelemetry/CHANGELOG.md b/opentelemetry/CHANGELOG.md index d9115489fd..b57647e5ab 100644 --- a/opentelemetry/CHANGELOG.md +++ b/opentelemetry/CHANGELOG.md @@ -4,7 +4,7 @@ ### Added -- [#1410](https://github.com/open-telemetry/opentelemetry-rust/pull/1410) Add experimental synchronous gauge. This is behind the conditional flag, and can be enabled by setting the environment variable RUSTFLAGS="--cfg=otel_unstable". +- [#1410](https://github.com/open-telemetry/opentelemetry-rust/pull/1410) Add experimental synchronous gauge. This is behind the feature flag, and can be enabled by enabling the feature `otel_unstable` for opentelemetry crate. - [#1410](https://github.com/open-telemetry/opentelemetry-rust/pull/1410) Guidelines to add new unstable/experimental features. diff --git a/opentelemetry/Cargo.toml b/opentelemetry/Cargo.toml index 98ae488386..2c6726db4c 100644 --- a/opentelemetry/Cargo.toml +++ b/opentelemetry/Cargo.toml @@ -38,7 +38,7 @@ metrics = [] testing = ["trace", "metrics"] logs = [] logs_level_enabled = ["logs"] -unstable = [] +otel_unstable = [] [dev-dependencies] opentelemetry_sdk = { path = "../opentelemetry-sdk" } # for documentation tests diff --git a/opentelemetry/src/metrics/meter.rs b/opentelemetry/src/metrics/meter.rs index 534acec9ae..f64fae6976 100644 --- a/opentelemetry/src/metrics/meter.rs +++ b/opentelemetry/src/metrics/meter.rs @@ -3,7 +3,7 @@ use std::any::Any; use std::borrow::Cow; use std::sync::Arc; -#[cfg(otel_unstable)] +#[cfg(feature = "otel_unstable")] use crate::metrics::Gauge; use crate::metrics::{ AsyncInstrumentBuilder, Counter, Histogram, InstrumentBuilder, InstrumentProvider, @@ -338,7 +338,7 @@ impl Meter { /// # Experimental /// This method is experimental and can be changed/removed in future releases. /// creates an instrument builder for recording independent values. - #[cfg(otel_unstable)] + #[cfg(feature = "otel_unstable")] pub fn u64_gauge( &self, name: impl Into>, @@ -349,7 +349,7 @@ impl Meter { /// # Experimental /// This method is experimental and can be changed/removed in future releases. /// creates an instrument builder for recording independent values. - #[cfg(otel_unstable)] + #[cfg(feature = "otel_unstable")] pub fn f64_gauge( &self, name: impl Into>, @@ -360,7 +360,7 @@ impl Meter { /// # Experimental /// This method is experimental and can be changed/removed in future releases. /// creates an instrument builder for recording indenpendent values. - #[cfg(feature = "sync-gauge-experimental")] + #[cfg(feature = "otel_unstable")] pub fn i64_gauge( &self, name: impl Into>, From 8b0601224c81be105ceb2fcc7d7c25576e954d0d Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Sat, 2 Dec 2023 00:33:36 +0000 Subject: [PATCH 11/12] update contributing --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4873692c37..1b1483eefa 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -154,7 +154,7 @@ It's important to regularly review and remove the `otel_unstable` flag from the The potential features include: - Stable and non-experimental features that are included in the specification to minimize compilation size. These could be separate feature flags for signals (like `logs`, `traces`, `metrics`) and runtimes (`rt-tokio`, `rt-tokio-current-thread`, `rt-async-std`). -- Stable and non-experimental features, although not part of the specification, are crucial for enhancing the tracing/log crate's functionality or boosting performance. Example: `logs_level_enabled`. +- Stable and non-experimental features, although not part of the specification, are crucial for enhancing the tracing/log crate's functionality or boosting performance. These features are also subject to discussion and approval by the OpenTelemetry Rust Maintainers. An example of such a feature is `logs_level_enabled`. All such features should adhere to naming convention `_` From f64806fdcc0ef95ffb46dbbbdf9992e675cbbca2 Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Sat, 2 Dec 2023 00:42:17 +0000 Subject: [PATCH 12/12] more updates --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1b1483eefa..a2dc337f11 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -153,7 +153,7 @@ It's important to regularly review and remove the `otel_unstable` flag from the The potential features include: -- Stable and non-experimental features that are included in the specification to minimize compilation size. These could be separate feature flags for signals (like `logs`, `traces`, `metrics`) and runtimes (`rt-tokio`, `rt-tokio-current-thread`, `rt-async-std`). +- Stable and non-experimental features that compliant to specification, and have a feature flag to minimize compilation size. Example: feature flags for signals (like `logs`, `traces`, `metrics`) and runtimes (`rt-tokio`, `rt-tokio-current-thread`, `rt-async-std`). - Stable and non-experimental features, although not part of the specification, are crucial for enhancing the tracing/log crate's functionality or boosting performance. These features are also subject to discussion and approval by the OpenTelemetry Rust Maintainers. An example of such a feature is `logs_level_enabled`. All such features should adhere to naming convention `_`