diff --git a/opentelemetry-otlp/CHANGELOG.md b/opentelemetry-otlp/CHANGELOG.md index 53a1d5b260..67b51e3284 100644 --- a/opentelemetry-otlp/CHANGELOG.md +++ b/opentelemetry-otlp/CHANGELOG.md @@ -2,6 +2,7 @@ ## vNext +- Fix `NoHttpClient` error when multiple HTTP client features are enabled by using priority-based selection (`reqwest-client` > `hyper-client` > `reqwest-blocking-client`). [#2994](https://github.com/open-telemetry/opentelemetry-rust/issues/2994) - Add partial success response handling for OTLP exporters (traces, metrics, logs) per OTLP spec. Exporters now log warnings when the server returns partial success responses with rejected items and error messages. [#865](https://github.com/open-telemetry/opentelemetry-rust/issues/865) - Refactor `internal-logs` feature in `opentelemetry-otlp` to reduce unnecessary dependencies[3191](https://github.com/open-telemetry/opentelemetry-rust/pull/3192) - Fixed [#2777](https://github.com/open-telemetry/opentelemetry rust/issues/2777) to properly handle `shutdown_with_timeout()` when using `grpc-tonic`. diff --git a/opentelemetry-otlp/src/exporter/http/mod.rs b/opentelemetry-otlp/src/exporter/http/mod.rs index 8860bc263b..1c01573b01 100644 --- a/opentelemetry-otlp/src/exporter/http/mod.rs +++ b/opentelemetry-otlp/src/exporter/http/mod.rs @@ -212,22 +212,14 @@ impl HttpExporterBuilder { #[allow(unused_mut)] // TODO - clippy thinks mut is not needed, but it is let mut http_client = self.http_config.client.take(); + // When multiple HTTP client features are enabled, we use a priority order + // to select the client. This follows Rust's feature unification principle + // where features should be additive. Priority (highest to lowest): + // 1. reqwest-client (async) + // 2. hyper-client + // 3. reqwest-blocking-client (default) if http_client.is_none() { - #[cfg(all( - not(feature = "reqwest-client"), - not(feature = "reqwest-blocking-client"), - feature = "hyper-client" - ))] - { - // TODO - support configuring custom connector and executor - http_client = Some(Arc::new(HyperClient::with_default_connector(timeout, None)) - as Arc); - } - #[cfg(all( - not(feature = "hyper-client"), - not(feature = "reqwest-blocking-client"), - feature = "reqwest-client" - ))] + #[cfg(feature = "reqwest-client")] { http_client = Some(Arc::new( reqwest::Client::builder() @@ -236,9 +228,15 @@ impl HttpExporterBuilder { .unwrap_or_default(), ) as Arc); } + #[cfg(all(not(feature = "reqwest-client"), feature = "hyper-client"))] + { + // TODO - support configuring custom connector and executor + http_client = Some(Arc::new(HyperClient::with_default_connector(timeout, None)) + as Arc); + } #[cfg(all( - not(feature = "hyper-client"), not(feature = "reqwest-client"), + not(feature = "hyper-client"), feature = "reqwest-blocking-client" ))] {