Repository: open-telemetry/opentelemetry-rust (Rust)

Issue:
[Bug]:  opentelemetry-prometheus can not be used with latest opentelemetry
### What happened?

opentelemetry-prometheus can not be used with latest opentelemetry (0.24)

I see https://github.com/open-telemetry/opentelemetry-rust/pull/1932 , do not know why update all others but exclude opentelemetry-prometheus ?

### API Version

0.24

### SDK Version

0.24

### What Exporter(s) are you seeing the problem on?

Prometheus

### Relevant log output

```shell
compliation failed:


error[E0277]: the trait bound `PrometheusExporter: MetricReader` is not satisfied
   --> src/telemetry.rs:63:22
    |
63  |         .with_reader(reader)
    |          ----------- ^^^^^^ the trait `MetricReader` is not implemented for `PrometheusExporter`
    |          |
    |          required by a bound introduced by this call
    |
    = help: the following other types implement trait `MetricReader`:
              ManualReader
              PeriodicReader
note: required by a bound in `MeterProviderBuilder::with_reader`
   --> xxxx/opentelemetry_sdk-0.24.1/src/metrics/meter_provider.rs:205:27
```
```



Discussion:
I'm also running into it. We could raise a PR bumping to opentelemetry 0.24, but I'm not really sure if it will be accepted, given https://github.com/open-telemetry/opentelemetry-rust/pull/1792 said

> Also removed opentelemetry-prometheus from CI for now, as it is not planned for the upcoming release : https://github.com/open-telemetry/opentelemetry-rust/issues/1719
we're actually also running into this with autometrics (https://github.com/autometrics-dev/autometrics-rs/pull/179). on the readme for the exporter it does say

> The development of prometheus exporter has halt until the Opentelemetry metrics API and SDK reaches 1.0. Current implementation is based on Opentelemetry API and SDK 0.23.

so that also speaks for that a pr to bump it wouldn't be accepted. i couldn't find any reasoning behind stopping development on the prometheus exporter, is there more reading into why?
I guess let's just give it a try :) I did the needed changes and created https://github.com/open-telemetry/opentelemetry-rust/pull/1957

Tested them using the following Cargo.toml and it seems to work
```
[patch.crates-io]
opentelemetry-prometheus = { git = "https://github.com/sbernauer/opentelemetry-rust", branch = "feat/otel-prom-0.17.0" }
```

@sbernauer wow, I also [made a workaround](https://github.com/ttys3/opentelemetry-rust/commit/e51611edcc340b2673b86b60daf3c3ccf7fd0b0c) 2 days ago

```toml
[patch.crates-io]
opentelemetry-prometheus = { git="https://github.com/ttys3/opentelemetry-rust.git", branch="opentelemetry-prometheus-sdk-0.24" }
```




Patch:
diff --git a/opentelemetry-prometheus/CHANGELOG.md b/opentelemetry-prometheus/CHANGELOG.md
index 0b1de5664e..6486650baa 100644
--- a/opentelemetry-prometheus/CHANGELOG.md
+++ b/opentelemetry-prometheus/CHANGELOG.md
@@ -2,6 +2,14 @@
 
 ## vNext
 
+## v0.17.0
+
+### Changed
+
+- Update `opentelemetry` dependency version to 0.24
+- Update `opentelemetry_sdk` dependency version to 0.24
+- Update `opentelemetry-semantic-conventions` dependency version to 0.16
+
 ## v0.16.0
 
 ### Added
diff --git a/opentelemetry-prometheus/Cargo.toml b/opentelemetry-prometheus/Cargo.toml
index 97d9d7abf2..3bbe65e35a 100644
--- a/opentelemetry-prometheus/Cargo.toml
+++ b/opentelemetry-prometheus/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "opentelemetry-prometheus"
-version = "0.16.0"
+version = "0.17.0"
 description = "Prometheus exporter for OpenTelemetry"
 homepage = "https://github.com/open-telemetry/opentelemetry-rust"
 repository = "https://github.com/open-telemetry/opentelemetry-rust"
@@ -21,13 +21,13 @@ rustdoc-args = ["--cfg", "docsrs"]
 
 [dependencies]
 once_cell = { workspace = true }
-opentelemetry = { version = "0.23", default-features = false, features = ["metrics"] }
-opentelemetry_sdk = { version = "0.23", default-features = false, features = ["metrics"] }
+opentelemetry = { version = "0.24", default-features = false, features = ["metrics"] }
+opentelemetry_sdk = { version = "0.24", default-features = false, features = ["metrics"] }
 prometheus = "0.13"
 protobuf = "2.14"
 
 [dev-dependencies]
-opentelemetry-semantic-conventions = { version = "0.15" }
+opentelemetry-semantic-conventions = { version = "0.16" }
 http-body-util = { workspace = true }
 hyper = { workspace = true, features = ["full"] }
 hyper-util = { workspace = true, features = ["full"] }
diff --git a/opentelemetry-prometheus/README.md b/opentelemetry-prometheus/README.md
index 9065e51fa3..360414b5aa 100644
--- a/opentelemetry-prometheus/README.md
+++ b/opentelemetry-prometheus/README.md
@@ -7,7 +7,7 @@
 [`Prometheus`] integration for applications instrumented with [`OpenTelemetry`]. 
 
 **The development of prometheus exporter has halt until the Opentelemetry metrics API and SDK reaches 1.0. Current 
-implementation is based on Opentelemetry API and SDK 0.23**.
+implementation is based on Opentelemetry API and SDK 0.24**.
 
 [![Crates.io: opentelemetry-prometheus](https://img.shields.io/crates/v/opentelemetry-prometheus.svg)](https://crates.io/crates/opentelemetry-prometheus)
 [![Documentation](https://docs.rs/opentelemetry-prometheus/badge.svg)](https://docs.rs/opentelemetry-prometheus)
diff --git a/opentelemetry-prometheus/examples/hyper.rs b/opentelemetry-prometheus/examples/hyper.rs
index 10d1402e98..692d21a719 100644
--- a/opentelemetry-prometheus/examples/hyper.rs
+++ b/opentelemetry-prometheus/examples/hyper.rs
@@ -8,7 +8,7 @@ use hyper::{
 use hyper_util::rt::{TokioExecutor, TokioIo};
 use once_cell::sync::Lazy;
 use opentelemetry::{
-    metrics::{Counter, Histogram, MeterProvider as _, Unit},
+    metrics::{Counter, Histogram, MeterProvider as _},
     KeyValue,
 };
 use opentelemetry_sdk::metrics::SdkMeterProvider;
@@ -88,12 +88,12 @@ pub async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
             .init(),
         http_body_gauge: meter
             .u64_histogram("example.http_response_size")
-            .with_unit(Unit::new("By"))
+            .with_unit("By")
             .with_description("The metrics HTTP response sizes in bytes.")
             .init(),
         http_req_histogram: meter
             .f64_histogram("example.http_request_duration")
-            .with_unit(Unit::new("ms"))
+            .with_unit("ms")
             .with_description("The HTTP request latencies in milliseconds.")
             .init(),
     });
diff --git a/opentelemetry-prometheus/src/lib.rs b/opentelemetry-prometheus/src/lib.rs
index c612bccac5..64cf6e5266 100644
--- a/opentelemetry-prometheus/src/lib.rs
+++ b/opentelemetry-prometheus/src/lib.rs
@@ -457,7 +457,10 @@ fn add_histogram_metric<T: Numeric>(
     // See: https://github.com/tikv/rust-prometheus/issues/393
 
     for dp in &histogram.data_points {
-        let kvs = get_attrs(&mut dp.attributes.iter(), extra);
+        let kvs = get_attrs(
+            &mut dp.attributes.iter().map(|kv| (&kv.key, &kv.value)),
+            extra,
+        );
         let bounds_len = dp.bounds.len();
         let (bucket, _) = dp.bounds.iter().enumerate().fold(
             (Vec::with_capacity(bounds_len), 0),
@@ -503,7 +506,10 @@ fn add_sum_metric<T: Numeric>(
     };
 
     for dp in &sum.data_points {
-        let kvs = get_attrs(&mut dp.attributes.iter(), extra);
+        let kvs = get_attrs(
+            &mut dp.attributes.iter().map(|kv| (&kv.key, &kv.value)),
+            extra,
+        );
 
         let mut pm = prometheus::proto::Metric::default();
         pm.set_label(protobuf::RepeatedField::from_vec(kvs));
@@ -535,7 +541,10 @@ fn add_gauge_metric<T: Numeric>(
     name: Cow<'static, str>,
 ) {
     for dp in &gauge.data_points {
-        let kvs = get_attrs(&mut dp.attributes.iter(), extra);
+        let kvs = get_attrs(
+            &mut dp.attributes.iter().map(|kv| (&kv.key, &kv.value)),
+            extra,
+        );
 
         let mut g = prometheus::proto::Gauge::default();
         g.set_value(dp.value.as_f64());
diff --git a/opentelemetry-prometheus/src/resource_selector.rs b/opentelemetry-prometheus/src/resource_selector.rs
index af244d0555..575c35c8e4 100644
--- a/opentelemetry-prometheus/src/resource_selector.rs
+++ b/opentelemetry-prometheus/src/resource_selector.rs
@@ -36,7 +36,7 @@ impl ResourceSelector {
             ResourceSelector::All => get_attrs(&mut resource.iter(), &[]),
             ResourceSelector::None => Vec::new(),
             ResourceSelector::KeyAllowList(keys) => {
-                get_attrs(&mut resource.iter().filter(|(k, _)| keys.contains(k)), &[])
+                get_attrs(&mut resource.iter().filter(|(k, _)| keys.contains(*k)), &[])
             }
         }
     }
diff --git a/opentelemetry-prometheus/src/utils.rs b/opentelemetry-prometheus/src/utils.rs
index d0a66a6e5a..a18c2bc96e 100644
--- a/opentelemetry-prometheus/src/utils.rs
+++ b/opentelemetry-prometheus/src/utils.rs
@@ -1,16 +1,15 @@
-use opentelemetry::metrics::Unit;
 use std::borrow::Cow;
 
 const NON_APPLICABLE_ON_PER_UNIT: [&str; 8] = ["1", "d", "h", "min", "s", "ms", "us", "ns"];
 
-pub(crate) fn get_unit_suffixes(unit: &Unit) -> Option<Cow<'static, str>> {
+pub(crate) fn get_unit_suffixes(unit: &str) -> Option<Cow<'static, str>> {
     // no unit return early
-    if unit.as_str().is_empty() {
+    if unit.is_empty() {
         return None;
     }
 
     // direct match with known units
-    if let Some(matched) = get_prom_units(unit.as_str()) {
+    if let Some(matched) = get_prom_units(unit) {
         return Some(Cow::Borrowed(matched));
     }
 
@@ -20,7 +19,7 @@ pub(crate) fn get_unit_suffixes(unit: &Unit) -> Option<Cow<'static, str>> {
     // e.g
     // "test/y" => "per_year"
     // "km/s" => "kilometers_per_second"
-    if let Some((first, second)) = unit.as_str().split_once('/') {
+    if let Some((first, second)) = unit.split_once('/') {
         return match (
             NON_APPLICABLE_ON_PER_UNIT.contains(&first),
             get_prom_units(first),
@@ -193,9 +192,8 @@ mod tests {
             // annotations
             ("{request}", None),
         ];
-        for (unit_str, expected_suffix) in test_cases {
-            let unit = Unit::new(unit_str);
-            assert_eq!(get_unit_suffixes(&unit), expected_suffix);
+        for (unit, expected_suffix) in test_cases {
+            assert_eq!(get_unit_suffixes(unit), expected_suffix);
         }
     }
 }


Test patch:
diff --git a/opentelemetry-prometheus/tests/integration_test.rs b/opentelemetry-prometheus/tests/integration_test.rs
index 149185e440..906290a092 100644
--- a/opentelemetry-prometheus/tests/integration_test.rs
+++ b/opentelemetry-prometheus/tests/integration_test.rs
@@ -3,7 +3,7 @@ use std::fs;
 use std::path::Path;
 use std::time::Duration;
 
-use opentelemetry::metrics::{Meter, MeterProvider as _, Unit};
+use opentelemetry::metrics::{Meter, MeterProvider as _};
 use opentelemetry::Key;
 use opentelemetry::KeyValue;
 use opentelemetry_prometheus::{ExporterBuilder, ResourceSelector};
@@ -54,7 +54,7 @@ fn prometheus_exporter_integration() {
                 let counter = meter
                     .f64_counter("foo")
                     .with_description("a simple counter")
-                    .with_unit(Unit::new("ms"))
+                    .with_unit("ms")
                     .init();
                 counter.add(5.0, &attrs);
                 counter.add(10.3, &attrs);
@@ -83,7 +83,7 @@ fn prometheus_exporter_integration() {
                 let counter = meter
                     .f64_counter("foo")
                     .with_description("a simple counter without a total suffix")
-                    .with_unit(Unit::new("ms"))
+                    .with_unit("ms")
                     .init();
                 counter.add(5.0, &attrs);
                 counter.add(10.3, &attrs);
@@ -106,7 +106,7 @@ fn prometheus_exporter_integration() {
                 let gauge = meter
                     .f64_up_down_counter("bar")
                     .with_description("a fun little gauge")
-                    .with_unit(Unit::new("1"))
+                    .with_unit("1")
                     .init();
                 gauge.add(1.0, &attrs);
                 gauge.add(-0.25, &attrs);
@@ -121,7 +121,7 @@ fn prometheus_exporter_integration() {
                 let histogram = meter
                     .f64_histogram("histogram_baz")
                     .with_description("a very nice histogram")
-                    .with_unit(Unit::new("By"))
+                    .with_unit("By")
                     .init();
                 histogram.record(23.0, &attrs);
                 histogram.record(7.0, &attrs);
@@ -147,7 +147,7 @@ fn prometheus_exporter_integration() {
                     .f64_counter("foo")
                     .with_description("a sanitary counter")
                     // This unit is not added to
-                    .with_unit(Unit::new("By"))
+                    .with_unit("By")
                     .init();
                 counter.add(5.0, &attrs);
                 counter.add(10.3, &attrs);
@@ -261,7 +261,7 @@ fn prometheus_exporter_integration() {
                 let gauge = meter
                     .i64_up_down_counter("bar")
                     .with_description("a fun little gauge")
-                    .with_unit(Unit::new("1"))
+                    .with_unit("1")
                     .init();
                 gauge.add(2, &attrs);
                 gauge.add(-1, &attrs);
@@ -279,7 +279,7 @@ fn prometheus_exporter_integration() {
                 let counter = meter
                     .u64_counter("bar")
                     .with_description("a fun little counter")
-                    .with_unit(Unit::new("By"))
+                    .with_unit("By")
                     .init();
                 counter.add(2, &attrs);
                 counter.add(1, &attrs);
@@ -317,7 +317,7 @@ fn prometheus_exporter_integration() {
                 let gauge = meter
                     .i64_up_down_counter("bar")
                     .with_description("a fun little gauge")
-                    .with_unit(Unit::new("1"))
+                    .with_unit("1")
                     .init();
                 gauge.add(2, &attrs);
                 gauge.add(-1, &attrs);
@@ -334,7 +334,7 @@ fn prometheus_exporter_integration() {
                 let gauge = meter
                     .i64_up_down_counter("bar")
                     .with_description("a fun little gauge")
-                    .with_unit(Unit::new("1"))
+                    .with_unit("1")
                     .init();
                 gauge.add(2, &attrs);
                 gauge.add(-1, &attrs);
@@ -456,7 +456,7 @@ fn multiple_scopes() {
             Some(vec![KeyValue::new("k", "v")]),
         )
         .u64_counter("foo")
-        .with_unit(Unit::new("ms"))
+        .with_unit("ms")
         .with_description("meter foo counter")
         .init();
     foo_counter.add(100, &[KeyValue::new("type", "foo")]);
@@ -469,7 +469,7 @@ fn multiple_scopes() {
             Some(vec![KeyValue::new("k", "v")]),
         )
         .u64_counter("bar")
-        .with_unit(Unit::new("ms"))
+        .with_unit("ms")
         .with_description("meter bar counter")
         .init();
     bar_counter.add(200, &[KeyValue::new("type", "bar")]);
@@ -507,7 +507,7 @@ fn duplicate_metrics() {
             record_metrics: Box::new(|meter_a, meter_b| {
                 let foo_a = meter_a
                     .u64_counter("foo")
-                    .with_unit(Unit::new("By"))
+                    .with_unit("By")
                     .with_description("meter counter foo")
                     .init();
 
@@ -515,7 +515,7 @@ fn duplicate_metrics() {
 
                 let foo_b = meter_b
                     .u64_counter("foo")
-                    .with_unit(Unit::new("By"))
+                    .with_unit("By")
                     .with_description("meter counter foo")
                     .init();
 
@@ -529,7 +529,7 @@ fn duplicate_metrics() {
             record_metrics: Box::new(|meter_a, meter_b| {
                 let foo_a = meter_a
                     .i64_up_down_counter("foo")
-                    .with_unit(Unit::new("By"))
+                    .with_unit("By")
                     .with_description("meter gauge foo")
                     .init();
 
@@ -537,7 +537,7 @@ fn duplicate_metrics() {
 
                 let foo_b = meter_b
                     .i64_up_down_counter("foo")
-                    .with_unit(Unit::new("By"))
+                    .with_unit("By")
                     .with_description("meter gauge foo")
                     .init();
 
@@ -551,7 +551,7 @@ fn duplicate_metrics() {
             record_metrics: Box::new(|meter_a, meter_b| {
                 let foo_a = meter_a
                     .u64_histogram("foo")
-                    .with_unit(Unit::new("By"))
+                    .with_unit("By")
                     .with_description("meter histogram foo")
                     .init();
 
@@ -559,7 +559,7 @@ fn duplicate_metrics() {
 
                 let foo_b = meter_b
                     .u64_histogram("foo")
-                    .with_unit(Unit::new("By"))
+                    .with_unit("By")
                     .with_description("meter histogram foo")
                     .init();
 
@@ -573,7 +573,7 @@ fn duplicate_metrics() {
             record_metrics: Box::new(|meter_a, meter_b| {
                 let bar_a = meter_a
                     .u64_counter("bar")
-                    .with_unit(Unit::new("By"))
+                    .with_unit("By")
                     .with_description("meter a bar")
                     .init();
 
@@ -581,7 +581,7 @@ fn duplicate_metrics() {
 
                 let bar_b = meter_b
                     .u64_counter("bar")
-                    .with_unit(Unit::new("By"))
+                    .with_unit("By")
                     .with_description("meter b bar")
                     .init();
 
@@ -598,7 +598,7 @@ fn duplicate_metrics() {
             record_metrics: Box::new(|meter_a, meter_b| {
                 let bar_a = meter_a
                     .i64_up_down_counter("bar")
-                    .with_unit(Unit::new("By"))
+                    .with_unit("By")
                     .with_description("meter a bar")
                     .init();
 
@@ -606,7 +606,7 @@ fn duplicate_metrics() {
 
                 let bar_b = meter_b
                     .i64_up_down_counter("bar")
-                    .with_unit(Unit::new("By"))
+                    .with_unit("By")
                     .with_description("meter b bar")
                     .init();
 
@@ -623,7 +623,7 @@ fn duplicate_metrics() {
             record_metrics: Box::new(|meter_a, meter_b| {
                 let bar_a = meter_a
                     .u64_histogram("bar")
-                    .with_unit(Unit::new("By"))
+                    .with_unit("By")
                     .with_description("meter a bar")
                     .init();
 
@@ -631,7 +631,7 @@ fn duplicate_metrics() {
 
                 let bar_b = meter_b
                     .u64_histogram("bar")
-                    .with_unit(Unit::new("By"))
+                    .with_unit("By")
                     .with_description("meter b bar")
                     .init();
 
@@ -648,7 +648,7 @@ fn duplicate_metrics() {
             record_metrics: Box::new(|meter_a, meter_b| {
                 let baz_a = meter_a
                     .u64_counter("bar")
-                    .with_unit(Unit::new("By"))
+                    .with_unit("By")
                     .with_description("meter bar")
                     .init();
 
@@ -656,7 +656,7 @@ fn duplicate_metrics() {
 
                 let baz_b = meter_b
                     .u64_counter("bar")
-                    .with_unit(Unit::new("ms"))
+                    .with_unit("ms")
                     .with_description("meter bar")
                     .init();
 
@@ -671,7 +671,7 @@ fn duplicate_metrics() {
             record_metrics: Box::new(|meter_a, meter_b| {
                 let bar_a = meter_a
                     .i64_up_down_counter("bar")
-                    .with_unit(Unit::new("By"))
+                    .with_unit("By")
                     .with_description("meter gauge bar")
                     .init();
 
@@ -679,7 +679,7 @@ fn duplicate_metrics() {
 
                 let bar_b = meter_b
                     .i64_up_down_counter("bar")
-                    .with_unit(Unit::new("ms"))
+                    .with_unit("ms")
                     .with_description("meter gauge bar")
                     .init();
 
@@ -694,7 +694,7 @@ fn duplicate_metrics() {
             record_metrics: Box::new(|meter_a, meter_b| {
                 let bar_a = meter_a
                     .u64_histogram("bar")
-                    .with_unit(Unit::new("By"))
+                    .with_unit("By")
                     .with_description("meter histogram bar")
                     .init();
 
@@ -702,7 +702,7 @@ fn duplicate_metrics() {
 
                 let bar_b = meter_b
                     .u64_histogram("bar")
-                    .with_unit(Unit::new("ms"))
+                    .with_unit("ms")
                     .with_description("meter histogram bar")
                     .init();
 
@@ -717,7 +717,7 @@ fn duplicate_metrics() {
             record_metrics: Box::new(|meter_a, _meter_b| {
                 let counter = meter_a
                     .u64_counter("foo")
-                    .with_unit(Unit::new("By"))
+                    .with_unit("By")
                     .with_description("meter foo")
                     .init();
 
@@ -725,7 +725,7 @@ fn duplicate_metrics() {
 
                 let gauge = meter_a
                     .i64_up_down_counter("foo_total")
-                    .with_unit(Unit::new("By"))
+                    .with_unit("By")
                     .with_description("meter foo")
                     .init();
 
@@ -743,7 +743,7 @@ fn duplicate_metrics() {
             record_metrics: Box::new(|meter_a, _meter_b| {
                 let foo_a = meter_a
                     .i64_up_down_counter("foo")
-                    .with_unit(Unit::new("By"))
+                    .with_unit("By")
                     .with_description("meter gauge foo")
                     .init();
 
@@ -751,7 +751,7 @@ fn duplicate_metrics() {
 
                 let foo_histogram_a = meter_a
                     .u64_histogram("foo")
-                    .with_unit(Unit::new("By"))
+                    .with_unit("By")
                     .with_description("meter histogram foo")
                     .init();