Skip to content

Commit

Permalink
feat: introduce both opentelemetry 0.26 and 0.27 exporter (#793)
Browse files Browse the repository at this point in the history
Signed-off-by: MrCroxx <[email protected]>
  • Loading branch information
MrCroxx authored Nov 25, 2024
1 parent 85d0ab8 commit fd2bed4
Show file tree
Hide file tree
Showing 9 changed files with 252 additions and 15 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ jobs:
cargo clippy --all-targets --features tokio-console -- -D warnings
cargo clippy --all-targets --features deadlock -- -D warnings
cargo clippy --all-targets --features tracing -- -D warnings
cargo clippy --all-targets --features prometheus,opentelemetry -- -D warnings
cargo clippy --all-targets --features prometheus,opentelemetry_0_26,opentelemetry_0_27 -- -D warnings
cargo clippy --all-targets -- -D warnings
- if: steps.cache.outputs.cache-hit != 'true'
uses: taiki-e/install-action@cargo-llvm-cov
Expand All @@ -182,7 +182,7 @@ jobs:
RUST_BACKTRACE: 1
CI: true
run: |
cargo llvm-cov --no-report nextest --features "strict_assertions,sanity,prometheus,opentelemetry"
cargo llvm-cov --no-report nextest --features "strict_assertions,sanity,prometheus,opentelemetry_0_26,opentelemetry_0_27"
- name: Run examples with coverage
env:
RUST_BACKTRACE: 1
Expand Down
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ tokio = { package = "madsim-tokio", version = "0.2", features = [
"fs",
] }
prometheus = "0.13"
opentelemetry = "0.27"
opentelemetry_0_27 = { package = "opentelemetry", version = "0.27" }
opentelemetry_0_26 = { package = "opentelemetry", version = "0.26" }

# foyer components
foyer-common = { version = "0.13.0-dev", path = "foyer-common" }
Expand Down
6 changes: 3 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ check:
./scripts/minimize-dashboards.sh
cargo sort -w
cargo fmt --all
cargo clippy --all-targets --features prometheus,opentelemetry
cargo clippy --all-targets --features prometheus,opentelemetry_0_26,opentelemetry_0_27

check-all:
shellcheck ./scripts/*
Expand All @@ -21,11 +21,11 @@ check-all:
cargo clippy --all-targets --features tokio-console
cargo clippy --all-targets --features sanity
cargo clippy --all-targets --features tracing
cargo clippy --all-targets --features prometheus,opentelemetry
cargo clippy --all-targets --features prometheus,opentelemetry_0_26,opentelemetry_0_27
cargo clippy --all-targets

test:
RUST_BACKTRACE=1 cargo nextest run --all --features "strict_assertions,sanity,prometheus,opentelemetry"
RUST_BACKTRACE=1 cargo nextest run --all --features "strict_assertions,sanity,prometheus,opentelemetry_0_26,opentelemetry_0_27"
RUST_BACKTRACE=1 cargo test --doc

test-ignored:
Expand Down
7 changes: 5 additions & 2 deletions foyer-common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ fastrace = { workspace = true }
futures = "0.3"
hashbrown = { workspace = true }
itertools = { workspace = true }
opentelemetry = { workspace = true, optional = true }
opentelemetry_0_26 = { workspace = true, optional = true }
opentelemetry_0_27 = { workspace = true, optional = true }
parking_lot = { workspace = true }
pin-project = "1"
prometheus = { workspace = true, optional = true }
Expand All @@ -34,7 +35,9 @@ rand = "0.8.5"
strict_assertions = []
tracing = ["fastrace/enable"]
prometheus = ["dep:prometheus"]
opentelemetry = ["dep:opentelemetry"]
opentelemetry = ["opentelemetry_0_27"]
opentelemetry_0_27 = ["dep:opentelemetry_0_27"]
opentelemetry_0_26 = ["dep:opentelemetry_0_26"]

[lints]
workspace = true
20 changes: 16 additions & 4 deletions foyer-common/src/metrics/model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -366,11 +366,23 @@ mod tests {
case(&PrometheusMetricsRegistry::new(prometheus::Registry::new()));
}

#[cfg(feature = "opentelemetry")]
#[cfg(feature = "opentelemetry_0_27")]
#[test]
fn test_metrics_opentelemetry() {
use crate::metrics::registry::opentelemetry::OpenTelemetryMetricsRegistry;
fn test_metrics_opentelemetry_0_27() {
use crate::metrics::registry::opentelemetry_0_27::OpenTelemetryMetricsRegistry;

case(&OpenTelemetryMetricsRegistry::new(opentelemetry::global::meter("test")));
case(&OpenTelemetryMetricsRegistry::new(opentelemetry_0_27::global::meter(
"test",
)));
}

#[cfg(feature = "opentelemetry_0_26")]
#[test]
fn test_metrics_opentelemetry_0_26() {
use crate::metrics::registry::opentelemetry_0_26::OpenTelemetryMetricsRegistry;

case(&OpenTelemetryMetricsRegistry::new(opentelemetry_0_26::global::meter(
"test",
)));
}
}
15 changes: 12 additions & 3 deletions foyer-common/src/metrics/registry/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,18 @@

/// Some phantom metrics components that do nothing.
pub mod noop;
/// OpenTelemetry metrics components.
#[cfg(feature = "opentelemetry")]
pub mod opentelemetry;

/// Prometheus metrics components.
#[cfg(feature = "prometheus")]
pub mod prometheus;

#[cfg(feature = "opentelemetry")]
pub use opentelemetry_0_27 as opentelemetry;

/// OpenTelemetry metrics components.
#[cfg(feature = "opentelemetry_0_27")]
pub mod opentelemetry_0_27;

/// OpenTelemetry metrics components.
#[cfg(feature = "opentelemetry_0_26")]
pub mod opentelemetry_0_26;
209 changes: 209 additions & 0 deletions foyer-common/src/metrics/registry/opentelemetry_0_26.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@
// Copyright 2024 foyer Project Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::sync::atomic::{AtomicU64, Ordering};

use itertools::Itertools;
use opentelemetry::{
metrics::{Counter as OtCounter, Gauge as OtGauge, Histogram as OtHistogram, Meter},
KeyValue,
};
use opentelemetry_0_26 as opentelemetry;

use crate::metrics::{CounterOps, CounterVecOps, GaugeOps, GaugeVecOps, HistogramOps, HistogramVecOps, RegistryOps};

/// OpenTelemetry counter metric.
#[derive(Debug)]
pub struct Counter {
counter: OtCounter<u64>,
labels: Vec<KeyValue>,
}

impl CounterOps for Counter {
fn increase(&self, val: u64) {
self.counter.add(val, &self.labels);
}
}

/// OpenTelemetry gauge metric.
#[derive(Debug)]
pub struct Gauge {
val: AtomicU64,
gauge: OtGauge<u64>,
labels: Vec<KeyValue>,
}

impl GaugeOps for Gauge {
fn increase(&self, val: u64) {
let v = self.val.fetch_add(val, Ordering::Relaxed) + val;
self.gauge.record(v, &self.labels);
}

fn decrease(&self, val: u64) {
let v = self.val.fetch_sub(val, Ordering::Relaxed) - val;
self.gauge.record(v, &self.labels);
}

fn absolute(&self, val: u64) {
self.val.store(val, Ordering::Relaxed);
self.gauge.record(val, &self.labels);
}
}

/// OpenTelemetry histogram metric.
#[derive(Debug)]
pub struct Histogram {
histogram: OtHistogram<f64>,
labels: Vec<KeyValue>,
}

impl HistogramOps for Histogram {
fn record(&self, val: f64) {
self.histogram.record(val, &self.labels);
}
}

/// OpenTelemetry metric vector.
#[derive(Debug)]
pub struct MetricVec {
meter: Meter,
name: &'static str,
desc: &'static str,
label_names: &'static [&'static str],
}

impl CounterVecOps for MetricVec {
fn counter(&self, labels: &[&str]) -> impl CounterOps {
let counter = self.meter.u64_counter(self.name).with_description(self.desc).init();
let labels = self
.label_names
.iter()
.zip_eq(labels.iter())
.map(|(name, label)| KeyValue::new(name.to_string(), label.to_string()))
.collect();
Counter { counter, labels }
}
}

impl GaugeVecOps for MetricVec {
fn gauge(&self, labels: &[&str]) -> impl GaugeOps {
let gauge = self.meter.u64_gauge(self.name).with_description(self.desc).init();
let labels = self
.label_names
.iter()
.zip_eq(labels.iter())
.map(|(name, label)| KeyValue::new(name.to_string(), label.to_string()))
.collect();
let val = AtomicU64::new(0);
Gauge { val, gauge, labels }
}
}

impl HistogramVecOps for MetricVec {
fn histogram(&self, labels: &[&str]) -> impl HistogramOps {
let histogram = self.meter.f64_histogram(self.name).with_description(self.desc).init();
let labels = self
.label_names
.iter()
.zip_eq(labels.iter())
.map(|(name, label)| KeyValue::new(name.to_string(), label.to_string()))
.collect();
Histogram { histogram, labels }
}
}

/// OpenTelemetry metrics registry.
#[derive(Debug)]
pub struct OpenTelemetryMetricsRegistry {
meter: Meter,
}

impl OpenTelemetryMetricsRegistry {
/// Create an OpenTelemetry metrics registry.
pub fn new(meter: Meter) -> Self {
Self { meter }
}
}

impl RegistryOps for OpenTelemetryMetricsRegistry {
fn register_counter_vec(
&self,
name: &'static str,
desc: &'static str,
label_names: &'static [&'static str],
) -> impl CounterVecOps {
let meter = self.meter.clone();
MetricVec {
meter,
name,
desc,
label_names,
}
}

fn register_gauge_vec(
&self,
name: &'static str,
desc: &'static str,
label_names: &'static [&'static str],
) -> impl GaugeVecOps {
let meter = self.meter.clone();
MetricVec {
meter,
name,
desc,
label_names,
}
}

fn register_histogram_vec(
&self,
name: &'static str,
desc: &'static str,
label_names: &'static [&'static str],
) -> impl HistogramVecOps {
let meter = self.meter.clone();
MetricVec {
meter,
name,
desc,
label_names,
}
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test() {
let meter = opentelemetry::global::meter("test");
let ot = OpenTelemetryMetricsRegistry::new(meter);

let cv = ot.register_counter_vec("test_counter_1", "test counter 1", &["label1", "label2"]);
let c = cv.counter(&["l1", "l2"]);
c.increase(42);

let gv = ot.register_gauge_vec("test_gauge_1", "test gauge 1", &["label1", "label2"]);
let g = gv.gauge(&["l1", "l2"]);
g.increase(514);
g.decrease(114);
g.absolute(114514);

let hv = ot.register_histogram_vec("test_histogram_1", "test histogram 1", &["label1", "label2"]);
let h = hv.histogram(&["l1", "l2"]);
h.record(114.514);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ use opentelemetry::{
metrics::{Counter as OtCounter, Gauge as OtGauge, Histogram as OtHistogram, Meter},
KeyValue,
};
use opentelemetry_0_27 as opentelemetry;

use crate::metrics::{CounterOps, CounterVecOps, GaugeOps, GaugeVecOps, HistogramOps, HistogramVecOps, RegistryOps};

Expand Down
2 changes: 2 additions & 0 deletions foyer/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ tracing = [
]
prometheus = ["foyer-common/prometheus"]
opentelemetry = ["foyer-common/opentelemetry"]
opentelemetry_0_27 = ["foyer-common/opentelemetry_0_27"]
opentelemetry_0_26 = ["foyer-common/opentelemetry_0_26"]

[lints]
workspace = true

0 comments on commit fd2bed4

Please sign in to comment.