Skip to content

Commit

Permalink
New metrics SDK (#1000)
Browse files Browse the repository at this point in the history
This patch updates the metrics SDK to the latest spec. The following
breaking changes are introduced.

Metrics API changes:

* Move `AttributeSet` to SDK as it's not mentioned in the spec or used
  in the api
* Consolidate `AsyncCounter`, `AsyncUpDownCounter`, and `AsyncGauge`
  into `AsyncInstrument` trait and add downcasting for observer
callbacks.
* Add `AsyncInstrumentBuilder` to allow per-instrument callback
  configuration.
* Allow metric `name` and `description` fields to be `Cow<'static, str>`
* Warn on metric misconfiguration when using instrument builder `init`
  rather than returning error
* Update `Meter::register_callback` to take a list of async instruments
  and validate they are registered in the callback through the
associated `Observer`
* Allow registered callbacks to be unregistered.

Metrics SDK changes:

* Introduce `Scope` as type alias for `InstrumentationLibrary`
* Update `Aggregation` to match aggregation spec
* Refactor `BasicController` to spec compliant `ManualReader`
* Refactor `PushController` to spec compliant `PeriodicReader`
* Update metric data fields to match spec, including exemplars.
* Split `MetricsExporter` into `Reader`s and `PushMetricExporter`s
* Add `View` implementation
* Remove `AtomicNumber`s
* Refactor `Processor`s into `Pipeline`

Metrics exporter changes:

* Update otlp exporter to match new metrics data
* Update otlp exporter configuration to allow aggregation and
  temporality selectors to be optional.
* Update prometheus exporter to match new metrics data

Example changes:
* Update otlp metrics and prometheus examples.
* Remove basic example as we should be focusing on the OTLP variants
  • Loading branch information
jtescher authored Mar 28, 2023
1 parent 879d6ff commit e4ef2a9
Show file tree
Hide file tree
Showing 123 changed files with 7,150 additions and 6,797 deletions.
2 changes: 2 additions & 0 deletions .github/codecov.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ coverage:
threshold: 0.5%

ignore:
- "examples"
- "opentelemetry/src/testing" # test harnesses
- "opentelemetry-jaeger/src/testing" # test harness
- "opentelemetry-jaeger/src/exporter/thrift" # auto generated files
- "opentelemetry-otlp/src/proto" # auto generated files
- "opentelemetry-proto/src/proto" # auto generated files
41 changes: 20 additions & 21 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -107,24 +107,23 @@ jobs:
continue-on-error: true
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
with:
submodules: true
- uses: actions-rs/toolchain@v1
with:
toolchain: nightly
components: rustfmt
override: true
- uses: actions-rs/cargo@v1
with:
command: test
args: -p opentelemetry -p opentelemetry_api -p opentelemetry_sdk -p opentelemetry-aws -p opentelemetry-jaeger -p opentelemetry-datadog -p opentelemetry-dynatrace -p opentelemetry-zipkin --all-features --no-fail-fast
env:
CARGO_INCREMENTAL: '0'
RUSTFLAGS: '-Zprofile -Ccodegen-units=1 -Cinline-threshold=0 -Clink-dead-code -Coverflow-checks=off -Cpanic=abort -Zpanic_abort_tests'
RUSTDOCFLAGS: '-Zprofile -Ccodegen-units=1 -Cinline-threshold=0 -Clink-dead-code -Coverflow-checks=off -Cpanic=abort -Zpanic_abort_tests'
- uses: actions-rs/grcov@v0.1
id: coverage
- uses: codecov/codecov-action@v1
with:
file: ${{ steps.coverage.outputs.report }}
- uses: actions/checkout@v3
with:
submodules: true
- uses: actions-rs/toolchain@v1
with:
toolchain: stable
components: rustfmt,llvm-tools-preview
override: true
- uses: arduino/setup-protoc@v1
- name: cargo install cargo-llvm-cov
uses: taiki-e/install-action@cargo-llvm-cov
- name: cargo generate-lockfile
if: hashFiles('Cargo.lock') == ''
run: cargo generate-lockfile
- name: cargo llvm-cov
run: cargo llvm-cov --locked --all-features --workspace --lcov --output-path lcov.info
- name: Upload to codecov.io
uses: codecov/codecov-action@v3
with:
fail_ci_if_error: true
1 change: 0 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ members = [
"examples/actix-udp",
"examples/async",
"examples/aws-xray",
"examples/basic",
"examples/basic-otlp",
"examples/basic-otlp-http",
"examples/datadog",
Expand Down
4 changes: 0 additions & 4 deletions examples/basic-otlp-http/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ use opentelemetry::{
};
use opentelemetry_otlp::WithExportConfig;
use std::error::Error;
use std::time::Duration;

fn init_tracer() -> Result<sdktrace::Tracer, TraceError> {
opentelemetry_otlp::new_pipeline()
Expand Down Expand Up @@ -44,9 +43,6 @@ async fn main() -> Result<(), Box<dyn Error + Send + Sync + 'static>> {
});
});

// wait for 1 minutes so that we could see metrics being pushed via OTLP every 10 seconds.
tokio::time::sleep(Duration::from_secs(60)).await;

global::shutdown_tracer_provider();

Ok(())
Expand Down
5 changes: 3 additions & 2 deletions examples/basic-otlp/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ publish = false

[dependencies]
futures-util = { version = "0.3", default-features = false, features = ["std"] }
lazy_static = "1.4"
opentelemetry = { path = "../../opentelemetry", features = ["rt-tokio", "metrics"] }
once_cell = "1.17"
opentelemetry_api = { path = "../../opentelemetry-api", features = ["metrics"] }
opentelemetry_sdk = { path = "../../opentelemetry-sdk", features = ["rt-tokio"] }
opentelemetry-otlp = { path = "../../opentelemetry-otlp", features = ["tonic", "metrics"] }
opentelemetry-semantic-conventions = { path = "../../opentelemetry-semantic-conventions" }
serde_json = "1.0"
Expand Down
46 changes: 19 additions & 27 deletions examples/basic-otlp/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,15 @@
use opentelemetry::global::shutdown_tracer_provider;
use opentelemetry::runtime;
use opentelemetry::sdk::export::metrics::aggregation::cumulative_temporality_selector;
use opentelemetry::sdk::metrics::controllers::BasicController;
use opentelemetry::sdk::metrics::selectors;
use opentelemetry::sdk::Resource;
use opentelemetry::trace::TraceError;
use opentelemetry::{global, sdk::trace as sdktrace};
use opentelemetry::{
use once_cell::sync::Lazy;
use opentelemetry_api::global;
use opentelemetry_api::global::shutdown_tracer_provider;
use opentelemetry_api::trace::TraceError;
use opentelemetry_api::{
metrics,
trace::{TraceContextExt, Tracer},
Context, Key, KeyValue,
};
use opentelemetry_otlp::{ExportConfig, WithExportConfig};
use opentelemetry_sdk::{metrics::MeterProvider, runtime, trace as sdktrace, Resource};
use std::error::Error;
use std::time::Duration;

fn init_tracer() -> Result<sdktrace::Tracer, TraceError> {
opentelemetry_otlp::new_pipeline()
Expand All @@ -29,20 +25,16 @@ fn init_tracer() -> Result<sdktrace::Tracer, TraceError> {
"trace-demo",
)])),
)
.install_batch(opentelemetry::runtime::Tokio)
.install_batch(runtime::Tokio)
}

fn init_metrics() -> metrics::Result<BasicController> {
fn init_metrics() -> metrics::Result<MeterProvider> {
let export_config = ExportConfig {
endpoint: "http://localhost:4317".to_string(),
..ExportConfig::default()
};
opentelemetry_otlp::new_pipeline()
.metrics(
selectors::simple::inexpensive(),
cumulative_temporality_selector(),
runtime::Tokio,
)
.metrics(runtime::Tokio)
.with_exporter(
opentelemetry_otlp::new_exporter()
.tonic()
Expand All @@ -54,22 +46,22 @@ fn init_metrics() -> metrics::Result<BasicController> {
const LEMONS_KEY: Key = Key::from_static_str("lemons");
const ANOTHER_KEY: Key = Key::from_static_str("ex.com/another");

lazy_static::lazy_static! {
static ref COMMON_ATTRIBUTES: [KeyValue; 4] = [
static COMMON_ATTRIBUTES: Lazy<[KeyValue; 4]> = Lazy::new(|| {
[
LEMONS_KEY.i64(10),
KeyValue::new("A", "1"),
KeyValue::new("B", "2"),
KeyValue::new("C", "3"),
];
}
]
});

#[tokio::main]
async fn main() -> Result<(), Box<dyn Error + Send + Sync + 'static>> {
// By binding the result to an unused variable, the lifetime of the variable
// matches the containing block, reporting traces and metrics during the whole
// execution.
let _ = init_tracer()?;
let metrics_controller = init_metrics()?;
let meter_provider = init_metrics()?;
let cx = Context::new();

let tracer = global::tracer("ex.com/basic");
Expand All @@ -79,7 +71,10 @@ async fn main() -> Result<(), Box<dyn Error + Send + Sync + 'static>> {
.f64_observable_gauge("ex.com.one")
.with_description("A gauge set to 1.0")
.init();
meter.register_callback(move |cx| gauge.observe(cx, 1.0, COMMON_ATTRIBUTES.as_ref()))?;

meter.register_callback(&[gauge.as_any()], move |observer| {
observer.observe_f64(&gauge, 1.0, COMMON_ATTRIBUTES.as_ref())
})?;

let histogram = meter.f64_histogram("ex.com.two").init();
histogram.record(&cx, 5.5, COMMON_ATTRIBUTES.as_ref());
Expand All @@ -102,11 +97,8 @@ async fn main() -> Result<(), Box<dyn Error + Send + Sync + 'static>> {
});
});

// wait for 1 minutes so that we could see metrics being pushed via OTLP every 10 seconds.
tokio::time::sleep(Duration::from_secs(60)).await;

shutdown_tracer_provider();
metrics_controller.stop(&cx)?;
meter_provider.shutdown()?;

Ok(())
}
13 changes: 0 additions & 13 deletions examples/basic/Cargo.toml

This file was deleted.

18 changes: 0 additions & 18 deletions examples/basic/README.md

This file was deleted.

109 changes: 0 additions & 109 deletions examples/basic/src/main.rs

This file was deleted.

Binary file removed examples/basic/trace.png
Binary file not shown.
8 changes: 4 additions & 4 deletions examples/dynatrace/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ publish = false
futures = "0.3"
http = "0.2"
lazy_static = "1.4"
opentelemetry = { path = "../../opentelemetry", default-features = false, features = ["trace"] }
opentelemetry = { version = "0.19", default-features = false, features = ["trace"] }
opentelemetry-dynatrace = { path = "../../opentelemetry-dynatrace" }
opentelemetry-http = { path = "../../opentelemetry-http", default-features = false }
opentelemetry-otlp = { path = "../../opentelemetry-otlp", default-features = false, features = ["http-proto", "reqwest-client"] }
opentelemetry-semantic-conventions = { path = "../../opentelemetry-semantic-conventions" }
opentelemetry-http = { version = "0.8", default-features = false }
opentelemetry-otlp = { version = "0.12", default-features = false, features = ["http-proto", "reqwest-client"] }
opentelemetry-semantic-conventions = "0.11"
tokio = { version = "1.0", features = ["full"] }
3 changes: 0 additions & 3 deletions examples/external-otlp-grpcio-async-std/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,9 +99,6 @@ async fn main() -> Result<(), Box<dyn Error + Send + Sync + 'static>> {
});
});

// wait for 1 minutes so that we could see metrics being pushed via OTLP every 10 seconds.
sleep(Duration::from_secs(60)).await;

shutdown_tracer_provider();

Ok(())
Expand Down
4 changes: 0 additions & 4 deletions examples/external-otlp-tonic-tokio/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ use std::{
env::{remove_var, set_var, var, vars},
error::Error,
str::FromStr,
time::Duration,
};

// Use the variables to try and export the example to any external collector that accepts otlp
Expand Down Expand Up @@ -101,9 +100,6 @@ async fn main() -> Result<(), Box<dyn Error + Send + Sync + 'static>> {
});
});

// wait for 1 minutes so that we could see metrics being pushed via OTLP every 10 seconds.
tokio::time::sleep(Duration::from_secs(60)).await;

shutdown_tracer_provider();

Ok(())
Expand Down
7 changes: 4 additions & 3 deletions examples/hyper-prometheus/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ publish = false
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
opentelemetry = { path = "../../opentelemetry", features = ["rt-tokio"] }
hyper = { version = "0.14", features = ["full"] }
once_cell = "1.17"
opentelemetry_api = { path = "../../opentelemetry-api", features = ["metrics"] }
opentelemetry_sdk = { path = "../../opentelemetry-sdk", features = ["metrics", "rt-tokio"] }
opentelemetry-prometheus = { path = "../../opentelemetry-prometheus" }
prometheus = "0.13"
lazy_static = "1.4"
hyper = { version = "0.14", features = ["full"] }
tokio = { version = "1", features = ["full"] }
Loading

0 comments on commit e4ef2a9

Please sign in to comment.