diff --git a/opentelemetry-otlp/CHANGELOG.md b/opentelemetry-otlp/CHANGELOG.md index 5ec7699d2a3..73d610bfc81 100644 --- a/opentelemetry-otlp/CHANGELOG.md +++ b/opentelemetry-otlp/CHANGELOG.md @@ -16,6 +16,7 @@ now use `.with_resource(RESOURCE::default())` to configure Resource when using These methods would also no longer set the global tracer provider. It would now be the responsibility of users to set it by calling `global::set_tracer_provider(tracer_provider.clone());`. Refer to the [basic-otlp](https://github.com/open-telemetry/opentelemetry-rust/blob/main/opentelemetry-otlp/examples/basic-otlp/src/main.rs) and [basic-otlp-http](https://github.com/open-telemetry/opentelemetry-rust/blob/main/opentelemetry-otlp/examples/basic-otlp-http/src/main.rs) examples on how to initialize OTLP Trace Exporter. - **Breaking** Correct the misspelling of "webkpi" to "webpki" in features [#1842](https://github.com/open-telemetry/opentelemetry-rust/pull/1842) - Bump MSRV to 1.70 [#1840](https://github.com/open-telemetry/opentelemetry-rust/pull/1840) +- Adds `hyper` feature to the basic-otlp-http example showing how to export with a custom Hyper Client ## v0.16.0 diff --git a/opentelemetry-otlp/examples/basic-otlp-http/Cargo.toml b/opentelemetry-otlp/examples/basic-otlp-http/Cargo.toml index 2c5e2d69cff..5357988ad5f 100644 --- a/opentelemetry-otlp/examples/basic-otlp-http/Cargo.toml +++ b/opentelemetry-otlp/examples/basic-otlp-http/Cargo.toml @@ -5,14 +5,25 @@ edition = "2021" license = "Apache-2.0" publish = false +[features] +default = ["reqwest"] +reqwest = ["opentelemetry-otlp/reqwest-client"] +hyper = ["dep:async-trait", "dep:http", "dep:hyper", "dep:opentelemetry-http", "dep:bytes"] + + [dependencies] once_cell = { workspace = true } opentelemetry = { path = "../../../opentelemetry" } opentelemetry_sdk = { path = "../../../opentelemetry-sdk", features = ["rt-tokio", "metrics", "logs"] } +opentelemetry-http = { path = "../../../opentelemetry-http", optional = true } opentelemetry-otlp = { path = "../..", features = ["http-proto", "reqwest-client", "logs"] } opentelemetry-appender-tracing = { path = "../../../opentelemetry-appender-tracing", default-features = false} opentelemetry-semantic-conventions = { path = "../../../opentelemetry-semantic-conventions" } +async-trait = { workspace = true, optional = true } +bytes = { workspace = true, optional = true } +http = { workspace = true, optional = true } +hyper = { workspace = true, features = ["client"], optional = true } tokio = { workspace = true, features = ["full"] } tracing = { workspace = true, features = ["std"]} tracing-core = { workspace = true } diff --git a/opentelemetry-otlp/examples/basic-otlp-http/README.md b/opentelemetry-otlp/examples/basic-otlp-http/README.md index 2608deafce5..91394b1560c 100644 --- a/opentelemetry-otlp/examples/basic-otlp-http/README.md +++ b/opentelemetry-otlp/examples/basic-otlp-http/README.md @@ -52,6 +52,14 @@ Run the app which exports logs, metrics and traces via OTLP to the collector cargo run ``` + +By default the app will use a `reqwest` client to send. A hyper 0.14 client can be used with the `hyper` feature enabled + +```shell +cargo run --no-default-features --features=hyper +``` + + ## View results You should be able to see something similar below with different time and ID in the same console that docker runs. diff --git a/opentelemetry-otlp/examples/basic-otlp-http/src/hyper.rs b/opentelemetry-otlp/examples/basic-otlp-http/src/hyper.rs new file mode 100644 index 00000000000..ff6e84a05dd --- /dev/null +++ b/opentelemetry-otlp/examples/basic-otlp-http/src/hyper.rs @@ -0,0 +1,45 @@ +use async_trait::async_trait; +use bytes::Bytes; +use http::{Request, Response}; +use hyper::{ + client::{connect::Connect, HttpConnector}, + Body, Client, +}; +use opentelemetry_http::{HttpClient, HttpError, ResponseExt}; + +pub struct HyperClient { + inner: hyper::Client, +} + +impl Default for HyperClient { + fn default() -> Self { + Self { + inner: Client::new(), + } + } +} + +impl std::fmt::Debug for HyperClient { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("HyperClient") + .field("inner", &self.inner) + .finish() + } +} + +#[async_trait] +impl HttpClient for HyperClient { + async fn send(&self, request: Request>) -> Result, HttpError> { + let request = request.map(Body::from); + + let (parts, body) = self + .inner + .request(request) + .await? + .error_for_status()? + .into_parts(); + let body = hyper::body::to_bytes(body).await?; + + Ok(Response::from_parts(parts, body)) + } +} diff --git a/opentelemetry-otlp/examples/basic-otlp-http/src/main.rs b/opentelemetry-otlp/examples/basic-otlp-http/src/main.rs index 205ac0362a4..857c163ea02 100644 --- a/opentelemetry-otlp/examples/basic-otlp-http/src/main.rs +++ b/opentelemetry-otlp/examples/basic-otlp-http/src/main.rs @@ -6,7 +6,7 @@ use opentelemetry::{ Key, KeyValue, }; use opentelemetry_appender_tracing::layer::OpenTelemetryTracingBridge; -use opentelemetry_otlp::WithExportConfig; +use opentelemetry_otlp::{HttpExporterBuilder, WithExportConfig}; use opentelemetry_sdk::trace::{self as sdktrace, Config}; use opentelemetry_sdk::{ logs::{self as sdklogs}, @@ -18,6 +18,9 @@ use tracing_subscriber::EnvFilter; use std::error::Error; +#[cfg(feature = "hyper")] +mod hyper; + static RESOURCE: Lazy = Lazy::new(|| { Resource::new(vec![KeyValue::new( opentelemetry_semantic_conventions::resource::SERVICE_NAME, @@ -25,26 +28,25 @@ static RESOURCE: Lazy = Lazy::new(|| { )]) }); +fn http_exporter() -> HttpExporterBuilder { + let exporter = opentelemetry_otlp::new_exporter().http(); + #[cfg(feature = "hyper")] + let exporter = exporter.with_http_client(hyper::HyperClient::default()); + exporter +} + fn init_logs() -> Result { opentelemetry_otlp::new_pipeline() .logging() .with_resource(RESOURCE.clone()) - .with_exporter( - opentelemetry_otlp::new_exporter() - .http() - .with_endpoint("http://localhost:4318/v1/logs"), - ) + .with_exporter(http_exporter().with_endpoint("http://localhost:4318/v1/logs")) .install_batch(opentelemetry_sdk::runtime::Tokio) } fn init_tracer_provider() -> Result { opentelemetry_otlp::new_pipeline() .tracing() - .with_exporter( - opentelemetry_otlp::new_exporter() - .http() - .with_endpoint("http://localhost:4318/v1/traces"), - ) + .with_exporter(http_exporter().with_endpoint("http://localhost:4318/v1/traces")) .with_trace_config(Config::default().with_resource(RESOURCE.clone())) .install_batch(opentelemetry_sdk::runtime::Tokio) } @@ -52,11 +54,7 @@ fn init_tracer_provider() -> Result { fn init_metrics() -> Result { let provider = opentelemetry_otlp::new_pipeline() .metrics(opentelemetry_sdk::runtime::Tokio) - .with_exporter( - opentelemetry_otlp::new_exporter() - .http() - .with_endpoint("http://localhost:4318/v1/metrics"), - ) + .with_exporter(http_exporter().with_endpoint("http://localhost:4318/v1/metrics")) .with_resource(RESOURCE.clone()) .build(); match provider {