From 387ad7c1c26aa08a6836b73fa1a5dab8316dce18 Mon Sep 17 00:00:00 2001 From: egtw Date: Tue, 6 Jun 2023 19:47:51 +0200 Subject: [PATCH 1/5] [WIP] OTLP push controller example initial commit --- examples/README.md | 1 + examples/otlp-push-controller/Cargo.toml | 12 +++++ examples/otlp-push-controller/README.md | 30 +++++++++++ .../otel-collector-config.yaml | 19 +++++++ examples/otlp-push-controller/src/main.rs | 51 +++++++++++++++++++ 5 files changed, 113 insertions(+) create mode 100644 examples/otlp-push-controller/Cargo.toml create mode 100644 examples/otlp-push-controller/README.md create mode 100644 examples/otlp-push-controller/otel-collector-config.yaml create mode 100644 examples/otlp-push-controller/src/main.rs diff --git a/examples/README.md b/examples/README.md index ec68296f..8f15bf5f 100644 --- a/examples/README.md +++ b/examples/README.md @@ -12,6 +12,7 @@ cargo run --package example-{name of example} - [axum](./axum) - Use autometrics to instrument HTTP handlers - [custom-metrics](./custom-metrics/) - Define your own custom metrics alongside the ones generated by autometrics (using any of the metrics collection crates) - [exemplars-tracing](./exemplars-tracing/) - Use fields from `tracing::Span`s as Prometheus exemplars +- [otlp-push-controller](./otlp-push-controller/) - Push autometrics via OTLP gRPC protocol. ## Full Example diff --git a/examples/otlp-push-controller/Cargo.toml b/examples/otlp-push-controller/Cargo.toml new file mode 100644 index 00000000..7d1dc193 --- /dev/null +++ b/examples/otlp-push-controller/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "example-otlp-push-controller" +version = "0.0.0" +publish = false +edition = "2021" + +[dependencies] +autometrics = { path = "../../autometrics", features = ["opentelemetry"] } +opentelemetry = { version = "0.19", features = ["metrics", "rt-tokio"] } +opentelemetry-otlp = { version = "0.12", features = ["tonic", "metrics"] } +opentelemetry-semantic-conventions = { version = "0.11" } +tokio = { version = "1", features = ["full"] } diff --git a/examples/otlp-push-controller/README.md b/examples/otlp-push-controller/README.md new file mode 100644 index 00000000..cf62d0ae --- /dev/null +++ b/examples/otlp-push-controller/README.md @@ -0,0 +1,30 @@ +# Autometrics + OTLP push controller + +This example demonstrates how you can push autometrics via OTLP gRPC protocol to an OTEL-Collector or another compatible solution. + +## ⚠️ Warning + +At this step, it's absolutely required that the version of the opentelemetry crates used in the project matches the version used as a dependency in `autometrics-rs` crate (See [Issue 91](https://github.com/autometrics-dev/autometrics-rs/issues/91)). + +## Running the example + +### Start a basic OTEL-Collector + +You can use the `otel-collector-config.yaml` file to start an otel-collector container that listen on 0.0.0.0:4317 for incoming otlp-gRPC traffic, and export received metrics to standard output. + +```bash +docker run -d --name otel-col \ + -p 4317:4317 -p 13133:13133 \ + -v $PWD/otel-collector-config.yaml:/etc/otelcol/config.yaml \ + otel/opentelemetry-collector:latest +``` + +### Execute example code + +```shell +cargo run -p example-otlp-push-controller +``` + +## OpenTelemetry Metrics Push Controller + +The metric push controller is implemented as from this [example](https://github.com/open-telemetry/opentelemetry-rust/blob/f20c9b40547ee20b6ec99414bb21abdd3a54d99b/examples/basic-otlp/src/main.rs#L35-L52) from `opentelemetry-rust` crate. diff --git a/examples/otlp-push-controller/otel-collector-config.yaml b/examples/otlp-push-controller/otel-collector-config.yaml new file mode 100644 index 00000000..731c5d09 --- /dev/null +++ b/examples/otlp-push-controller/otel-collector-config.yaml @@ -0,0 +1,19 @@ +receivers: + otlp: + protocols: + grpc: + endpoint: 0.0.0.0:4317 + +exporters: + logging: + loglevel: debug + +processors: + batch: + +service: + pipelines: + metrics: + receivers: [otlp] + processors: [] + exporters: [logging] diff --git a/examples/otlp-push-controller/src/main.rs b/examples/otlp-push-controller/src/main.rs new file mode 100644 index 00000000..30d24a2b --- /dev/null +++ b/examples/otlp-push-controller/src/main.rs @@ -0,0 +1,51 @@ +use autometrics::autometrics; +use opentelemetry::{runtime, Context}; +use opentelemetry::sdk::export::metrics::aggregation::cumulative_temporality_selector; +use opentelemetry::sdk::metrics::controllers::BasicController; +use opentelemetry::sdk::metrics::selectors; +use opentelemetry::metrics; +use opentelemetry_otlp::{ExportConfig, WithExportConfig}; +use tokio::time::sleep; +use std::error::Error; +use std::time::Duration; + +fn init_metrics() -> metrics::Result { + 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, + ) + .with_exporter( + opentelemetry_otlp::new_exporter() + .tonic() + .with_export_config(export_config), + ) + .build() +} + +#[tokio::main] +async fn main() -> Result<(), Box> { + let meter_provider = init_metrics()?; + let cx = Context::current(); + + for numb in 0..10 { + do_stuff(numb).await; + } + + println!("Waiting so that we could see metrics being pushed via OTLP every 10 seconds..."); + sleep(Duration::from_secs(60)).await; + meter_provider.stop(&cx)?; + + Ok(()) +} + +#[autometrics] +async fn do_stuff(numb: u64) { + println!("Doing stuff for {} seconds...", numb); + sleep(Duration::from_secs(numb)).await; +} \ No newline at end of file From ae2129150521091f1a96d0b30a26f00c21e36bdc Mon Sep 17 00:00:00 2001 From: Emanuele Granato <48388718+egtwp@users.noreply.github.com> Date: Wed, 7 Jun 2023 17:20:14 +0200 Subject: [PATCH 2/5] Put opentelemetry version warning in cargo.toml Co-authored-by: Evan Schwartz --- examples/otlp-push-controller/Cargo.toml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/examples/otlp-push-controller/Cargo.toml b/examples/otlp-push-controller/Cargo.toml index 7d1dc193..36a63a10 100644 --- a/examples/otlp-push-controller/Cargo.toml +++ b/examples/otlp-push-controller/Cargo.toml @@ -6,6 +6,8 @@ edition = "2021" [dependencies] autometrics = { path = "../../autometrics", features = ["opentelemetry"] } +# Note that the version of the opentelemetry crate MUST match +# the version used by autometrics opentelemetry = { version = "0.19", features = ["metrics", "rt-tokio"] } opentelemetry-otlp = { version = "0.12", features = ["tonic", "metrics"] } opentelemetry-semantic-conventions = { version = "0.11" } From dbfc2f1ae14cef6d94e1689580b7ba113f3e20dc Mon Sep 17 00:00:00 2001 From: egtw Date: Wed, 7 Jun 2023 18:08:28 +0200 Subject: [PATCH 3/5] Implemented code review suggestions --- examples/README.md | 2 +- .../Cargo.toml | 2 +- examples/opentelemetry-push/README.md | 105 ++++++++++++++++++ .../otel-collector-config.yml} | 0 .../src/main.rs | 15 ++- examples/otlp-push-controller/README.md | 30 ----- 6 files changed, 114 insertions(+), 40 deletions(-) rename examples/{otlp-push-controller => opentelemetry-push}/Cargo.toml (92%) create mode 100644 examples/opentelemetry-push/README.md rename examples/{otlp-push-controller/otel-collector-config.yaml => opentelemetry-push/otel-collector-config.yml} (100%) rename examples/{otlp-push-controller => opentelemetry-push}/src/main.rs (88%) delete mode 100644 examples/otlp-push-controller/README.md diff --git a/examples/README.md b/examples/README.md index 8f15bf5f..e18fe696 100644 --- a/examples/README.md +++ b/examples/README.md @@ -12,7 +12,7 @@ cargo run --package example-{name of example} - [axum](./axum) - Use autometrics to instrument HTTP handlers - [custom-metrics](./custom-metrics/) - Define your own custom metrics alongside the ones generated by autometrics (using any of the metrics collection crates) - [exemplars-tracing](./exemplars-tracing/) - Use fields from `tracing::Span`s as Prometheus exemplars -- [otlp-push-controller](./otlp-push-controller/) - Push autometrics via OTLP gRPC protocol. +- [opentelemetry-push](./opentelemetry-push/) - Push autometrics via OTLP gRPC protocol. ## Full Example diff --git a/examples/otlp-push-controller/Cargo.toml b/examples/opentelemetry-push/Cargo.toml similarity index 92% rename from examples/otlp-push-controller/Cargo.toml rename to examples/opentelemetry-push/Cargo.toml index 36a63a10..be1b7988 100644 --- a/examples/otlp-push-controller/Cargo.toml +++ b/examples/opentelemetry-push/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "example-otlp-push-controller" +name = "example-opentelemetry-push" version = "0.0.0" publish = false edition = "2021" diff --git a/examples/opentelemetry-push/README.md b/examples/opentelemetry-push/README.md new file mode 100644 index 00000000..3827a601 --- /dev/null +++ b/examples/opentelemetry-push/README.md @@ -0,0 +1,105 @@ +# Autometrics + OTLP push controller + +This example demonstrates how you can push autometrics via OTLP gRPC protocol to an OTEL-Collector or another compatible solution. + +## Running the example + +### Start a basic OTEL-Collector + +You can use the [`otel-collector-config.yml`](./otel-collector-config.yml) file to start an otel-collector container that listen on 0.0.0.0:4317 for incoming otlp-gRPC traffic, and export received metrics to standard output. + +Run the following command in a second terminal to start a container in interactive mode: + +```bash +docker run -it --name otel-col \ + -p 4317:4317 -p 13133:13133 \ + -v $PWD/otel-collector-config.yml:/etc/otelcol/config.yaml \ + otel/opentelemetry-collector:latest +``` + +You should see the collector initialization output, that should end with something like: + +```text +... +2023-06-07T15:56:42.617Z info otlpreceiver@v0.75.0/otlp.go:94 Starting GRPC server {"kind": "receiver", "name": "otlp", "data_type": "metrics", "endpoint": "0.0.0.0:4317"} +2023-06-07T15:56:42.618Z info service/service.go:146 Everything is ready. Begin running and processing data. +``` + +### Execute example code + +Then come back on your primary shell and run this example: + +```shell +cargo run -p example-opentelemetry-push +``` + +### Check the output + +On the stdout of the terminal where you started the opentelemetry-collector container, you should see the metrics generated by autometrics macro being pushed every 10 seconds since example exit, like: + +```text +... +Metric #0 +Descriptor: + -> Name: function.calls.count + -> Description: Autometrics counter for tracking function calls + -> Unit: + -> DataType: Sum + -> IsMonotonic: true + -> AggregationTemporality: Cumulative +NumberDataPoints #0 +Data point attributes: + -> caller: Str() + -> function: Str(do_stuff) + -> module: Str(example_opentelemetry_push) +StartTimestamp: 2023-06-07 16:01:08.549300623 +0000 UTC +Timestamp: 2023-06-07 16:01:48.551531429 +0000 UTC +Value: 10 +Metric #1 +Descriptor: + -> Name: build_info + -> Description: Autometrics info metric for tracking software version and build details + -> Unit: + -> DataType: Sum + -> IsMonotonic: false + -> AggregationTemporality: Cumulative +NumberDataPoints #0 +Data point attributes: + -> branch: Str() + -> commit: Str() + -> version: Str(0.0.0) +StartTimestamp: 2023-06-07 16:01:08.549300623 +0000 UTC +Timestamp: 2023-06-07 16:01:48.551531429 +0000 UTC +Value: 1.000000 +Metric #2 +Descriptor: + -> Name: function.calls.duration + -> Description: Autometrics histogram for tracking function call duration + -> Unit: + -> DataType: Sum + -> IsMonotonic: false + -> AggregationTemporality: Cumulative +NumberDataPoints #0 +Data point attributes: + -> function: Str(do_stuff) + -> module: Str(example_opentelemetry_push) +StartTimestamp: 2023-06-07 16:01:08.549300623 +0000 UTC +Timestamp: 2023-06-07 16:01:48.551531429 +0000 UTC +Value: 0.000122 + {"kind": "exporter", "data_type": "metrics", "name": "logging"} +... +``` + +### Cleanup + +In the end, to stop the opentelemetry collector container just hit `^C`. + +Then delete the container with + +```bash +docker rm otel-col +``` + +## OpenTelemetry Metrics Push Controller + +The metric push controller is implemented as from this [example](https://github.com/open-telemetry/opentelemetry-rust/blob/f20c9b40547ee20b6ec99414bb21abdd3a54d99b/examples/basic-otlp/src/main.rs#L35-L52) from `opentelemetry-rust` crate. diff --git a/examples/otlp-push-controller/otel-collector-config.yaml b/examples/opentelemetry-push/otel-collector-config.yml similarity index 100% rename from examples/otlp-push-controller/otel-collector-config.yaml rename to examples/opentelemetry-push/otel-collector-config.yml diff --git a/examples/otlp-push-controller/src/main.rs b/examples/opentelemetry-push/src/main.rs similarity index 88% rename from examples/otlp-push-controller/src/main.rs rename to examples/opentelemetry-push/src/main.rs index 30d24a2b..65a1da29 100644 --- a/examples/otlp-push-controller/src/main.rs +++ b/examples/opentelemetry-push/src/main.rs @@ -28,13 +28,18 @@ fn init_metrics() -> metrics::Result { .build() } +#[autometrics] +fn do_stuff() { + println!("Doing stuff..."); +} + #[tokio::main] async fn main() -> Result<(), Box> { let meter_provider = init_metrics()?; let cx = Context::current(); - for numb in 0..10 { - do_stuff(numb).await; + for _ in 0..10 { + do_stuff(); } println!("Waiting so that we could see metrics being pushed via OTLP every 10 seconds..."); @@ -43,9 +48,3 @@ async fn main() -> Result<(), Box> { Ok(()) } - -#[autometrics] -async fn do_stuff(numb: u64) { - println!("Doing stuff for {} seconds...", numb); - sleep(Duration::from_secs(numb)).await; -} \ No newline at end of file diff --git a/examples/otlp-push-controller/README.md b/examples/otlp-push-controller/README.md deleted file mode 100644 index cf62d0ae..00000000 --- a/examples/otlp-push-controller/README.md +++ /dev/null @@ -1,30 +0,0 @@ -# Autometrics + OTLP push controller - -This example demonstrates how you can push autometrics via OTLP gRPC protocol to an OTEL-Collector or another compatible solution. - -## ⚠️ Warning - -At this step, it's absolutely required that the version of the opentelemetry crates used in the project matches the version used as a dependency in `autometrics-rs` crate (See [Issue 91](https://github.com/autometrics-dev/autometrics-rs/issues/91)). - -## Running the example - -### Start a basic OTEL-Collector - -You can use the `otel-collector-config.yaml` file to start an otel-collector container that listen on 0.0.0.0:4317 for incoming otlp-gRPC traffic, and export received metrics to standard output. - -```bash -docker run -d --name otel-col \ - -p 4317:4317 -p 13133:13133 \ - -v $PWD/otel-collector-config.yaml:/etc/otelcol/config.yaml \ - otel/opentelemetry-collector:latest -``` - -### Execute example code - -```shell -cargo run -p example-otlp-push-controller -``` - -## OpenTelemetry Metrics Push Controller - -The metric push controller is implemented as from this [example](https://github.com/open-telemetry/opentelemetry-rust/blob/f20c9b40547ee20b6ec99414bb21abdd3a54d99b/examples/basic-otlp/src/main.rs#L35-L52) from `opentelemetry-rust` crate. From dcfad4b1778aff86f1320c459a64fa4f96e10904 Mon Sep 17 00:00:00 2001 From: egtw Date: Fri, 16 Jun 2023 10:11:04 +0200 Subject: [PATCH 4/5] Reduced metrics push interval + used `autometrics_example_util::sleep_random_duration` to simulate random work --- examples/opentelemetry-push/Cargo.toml | 1 + examples/opentelemetry-push/src/main.rs | 14 +++++++++----- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/examples/opentelemetry-push/Cargo.toml b/examples/opentelemetry-push/Cargo.toml index be1b7988..beac86d4 100644 --- a/examples/opentelemetry-push/Cargo.toml +++ b/examples/opentelemetry-push/Cargo.toml @@ -6,6 +6,7 @@ edition = "2021" [dependencies] autometrics = { path = "../../autometrics", features = ["opentelemetry"] } +autometrics-example-util = { path = "../util" } # Note that the version of the opentelemetry crate MUST match # the version used by autometrics opentelemetry = { version = "0.19", features = ["metrics", "rt-tokio"] } diff --git a/examples/opentelemetry-push/src/main.rs b/examples/opentelemetry-push/src/main.rs index 65a1da29..ca2ef31d 100644 --- a/examples/opentelemetry-push/src/main.rs +++ b/examples/opentelemetry-push/src/main.rs @@ -1,4 +1,5 @@ use autometrics::autometrics; +use autometrics_example_util::sleep_random_duration; use opentelemetry::{runtime, Context}; use opentelemetry::sdk::export::metrics::aggregation::cumulative_temporality_selector; use opentelemetry::sdk::metrics::controllers::BasicController; @@ -14,6 +15,7 @@ fn init_metrics() -> metrics::Result { endpoint: "http://localhost:4317".to_string(), ..ExportConfig::default() }; + let push_interval = Duration::from_secs(1); opentelemetry_otlp::new_pipeline() .metrics( selectors::simple::inexpensive(), @@ -25,12 +27,14 @@ fn init_metrics() -> metrics::Result { .tonic() .with_export_config(export_config), ) + .with_period(push_interval) .build() } #[autometrics] -fn do_stuff() { +async fn do_stuff() { println!("Doing stuff..."); + sleep_random_duration().await; } #[tokio::main] @@ -38,12 +42,12 @@ async fn main() -> Result<(), Box> { let meter_provider = init_metrics()?; let cx = Context::current(); - for _ in 0..10 { - do_stuff(); + for _ in 0..100 { + do_stuff().await; } - println!("Waiting so that we could see metrics being pushed via OTLP every 10 seconds..."); - sleep(Duration::from_secs(60)).await; + println!("Waiting so that we could see metrics going down..."); + sleep(Duration::from_secs(10)).await; meter_provider.stop(&cx)?; Ok(()) From 28770437e7ef32c82daaa6161d2c71b941a1363c Mon Sep 17 00:00:00 2001 From: Emanuele Granato <48388718+egtwp@users.noreply.github.com> Date: Fri, 16 Jun 2023 18:04:39 +0200 Subject: [PATCH 5/5] Apply typos fix from code review Co-authored-by: Evan Schwartz --- examples/README.md | 2 +- examples/opentelemetry-push/README.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/README.md b/examples/README.md index e18fe696..c9af51be 100644 --- a/examples/README.md +++ b/examples/README.md @@ -12,7 +12,7 @@ cargo run --package example-{name of example} - [axum](./axum) - Use autometrics to instrument HTTP handlers - [custom-metrics](./custom-metrics/) - Define your own custom metrics alongside the ones generated by autometrics (using any of the metrics collection crates) - [exemplars-tracing](./exemplars-tracing/) - Use fields from `tracing::Span`s as Prometheus exemplars -- [opentelemetry-push](./opentelemetry-push/) - Push autometrics via OTLP gRPC protocol. +- [opentelemetry-push](./opentelemetry-push/) - Push metrics to an OpenTelemetry Collector via the OTLP gRPC protocol ## Full Example diff --git a/examples/opentelemetry-push/README.md b/examples/opentelemetry-push/README.md index 3827a601..bb2358b7 100644 --- a/examples/opentelemetry-push/README.md +++ b/examples/opentelemetry-push/README.md @@ -1,12 +1,12 @@ # Autometrics + OTLP push controller -This example demonstrates how you can push autometrics via OTLP gRPC protocol to an OTEL-Collector or another compatible solution. +This example demonstrates how you can push autometrics via OTLP gRPC protocol to the [OpenTelemetry Collector](https://opentelemetry.io/docs/collector/) or another OTel-compatible solution. ## Running the example ### Start a basic OTEL-Collector -You can use the [`otel-collector-config.yml`](./otel-collector-config.yml) file to start an otel-collector container that listen on 0.0.0.0:4317 for incoming otlp-gRPC traffic, and export received metrics to standard output. +You can use the [`otel-collector-config.yml`](./otel-collector-config.yml) file to start an otel-collector container that listens on 0.0.0.0:4317 for incoming otlp-gRPC traffic, and exports the metrics it receives to stdout. Run the following command in a second terminal to start a container in interactive mode: