Skip to content

Commit a047fad

Browse files
authored
Merge branch 'main' into move-errors-to-sdk
2 parents 9cf5898 + 3742953 commit a047fad

File tree

18 files changed

+323
-240
lines changed

18 files changed

+323
-240
lines changed

.github/workflows/ci.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -73,11 +73,11 @@ jobs:
7373
- uses: actions/checkout@v4
7474
- uses: dtolnay/rust-toolchain@nightly
7575
with:
76-
toolchain: nightly-2024-05-01
76+
toolchain: nightly-2024-06-30
7777
components: rustfmt
7878
- name: external-type-check
7979
run: |
80-
cargo install cargo-check-external-types
80+
cargo install cargo-check-external-types@0.1.13
8181
cd ${{ matrix.example }}
8282
cargo check-external-types --config allowed-external-types.toml
8383
non-default-examples:

Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ hyper-util = "0.1"
3030
log = "0.4.21"
3131
once_cell = "1.13"
3232
ordered-float = "4.0"
33-
pin-project-lite = "=0.2.14" # 0.2.15 is failing for cargo-check-external-types
33+
pin-project-lite = "0.2"
3434
prost = "0.13"
3535
prost-build = "0.13"
3636
prost-types = "0.13"

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ observability tools.
4040

4141
*OpenTelemetry Rust is not introducing a new end user callable Logging API.
4242
Instead, it provides [Logs Bridge
43-
API](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/logs/bridge-api.md),
43+
API](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/logs/api.md),
4444
that allows one to write log appenders that can bridge existing logging
4545
libraries to the OpenTelemetry log data model. The following log appenders are
4646
available:

opentelemetry-http/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ bytes = { workspace = true }
2020
http = { workspace = true }
2121
http-body-util = { workspace = true, optional = true }
2222
hyper = { workspace = true, optional = true }
23-
hyper-util = { workspace = true, features = ["client-legacy", "http2"], optional = true }
23+
hyper-util = { workspace = true, features = ["client-legacy", "http1", "http2"], optional = true }
2424
opentelemetry = { version = "0.26", path = "../opentelemetry", features = ["trace"] }
2525
reqwest = { workspace = true, features = ["blocking"], optional = true }
2626
tokio = { workspace = true, features = ["time"], optional = true }

opentelemetry-http/src/lib.rs

+23-17
Original file line numberDiff line numberDiff line change
@@ -108,47 +108,53 @@ pub mod hyper {
108108
use http::HeaderValue;
109109
use http_body_util::{BodyExt, Full};
110110
use hyper::body::{Body as HttpBody, Frame};
111-
use hyper_util::client::legacy::{connect::Connect, Client};
111+
use hyper_util::client::legacy::{
112+
connect::{Connect, HttpConnector},
113+
Client,
114+
};
112115
use std::fmt::Debug;
113116
use std::pin::Pin;
114117
use std::task::{self, Poll};
115118
use std::time::Duration;
116119
use tokio::time;
117120

118121
#[derive(Debug, Clone)]
119-
pub struct HyperClient<C> {
122+
pub struct HyperClient<C = HttpConnector>
123+
where
124+
C: Connect + Clone + Send + Sync + 'static,
125+
{
120126
inner: Client<C, Body>,
121127
timeout: Duration,
122128
authorization: Option<HeaderValue>,
123129
}
124130

125-
impl<C> HyperClient<C> {
126-
pub fn new_with_timeout(inner: Client<C, Body>, timeout: Duration) -> Self {
131+
impl<C> HyperClient<C>
132+
where
133+
C: Connect + Clone + Send + Sync + 'static,
134+
{
135+
pub fn new(connector: C, timeout: Duration, authorization: Option<HeaderValue>) -> Self {
136+
// TODO - support custom executor
137+
let inner = Client::builder(hyper_util::rt::TokioExecutor::new()).build(connector);
127138
Self {
128139
inner,
129140
timeout,
130-
authorization: None,
141+
authorization,
131142
}
132143
}
144+
}
133145

134-
pub fn new_with_timeout_and_authorization_header(
135-
inner: Client<C, Body>,
146+
impl HyperClient<HttpConnector> {
147+
/// Creates a new `HyperClient` with a default `HttpConnector`.
148+
pub fn with_default_connector(
136149
timeout: Duration,
137-
authorization: HeaderValue,
150+
authorization: Option<HeaderValue>,
138151
) -> Self {
139-
Self {
140-
inner,
141-
timeout,
142-
authorization: Some(authorization),
143-
}
152+
Self::new(HttpConnector::new(), timeout, authorization)
144153
}
145154
}
146155

147156
#[async_trait]
148-
impl<C> HttpClient for HyperClient<C>
149-
where
150-
C: Connect + Send + Sync + Clone + Debug + 'static,
151-
{
157+
impl HttpClient for HyperClient {
152158
async fn send(&self, request: Request<Vec<u8>>) -> Result<Response<Bytes>, HttpError> {
153159
let (parts, body) = request.into_parts();
154160
let mut request = Request::from_parts(parts, Body(Full::from(body)));

opentelemetry-otlp/CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@ Released 2024-Sep-30
5353
- `MetricsExporter` -> `MetricExporter`
5454
- `MetricsExporterBuilder` -> `MetricExporterBuilder`
5555

56+
- [#2263](https://github.com/open-telemetry/opentelemetry-rust/pull/2263)
57+
Support `hyper` client for opentelemetry-otlp. This can be enabled using flag `hyper-client`.
58+
Refer example: https://github.com/open-telemetry/opentelemetry-rust/tree/main/opentelemetry-otlp/examples/basic-otlp-http
59+
5660
## v0.25.0
5761

5862
- Update `opentelemetry` dependency version to 0.25

opentelemetry-otlp/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ reqwest-blocking-client = ["reqwest/blocking", "opentelemetry-http/reqwest"]
8080
reqwest-client = ["reqwest", "opentelemetry-http/reqwest"]
8181
reqwest-rustls = ["reqwest", "opentelemetry-http/reqwest-rustls"]
8282
reqwest-rustls-webpki-roots = ["reqwest", "opentelemetry-http/reqwest-rustls-webpki-roots"]
83+
hyper-client = ["opentelemetry-http/hyper"]
8384

8485
# test
8586
integration-testing = ["tonic", "prost", "tokio/full", "trace"]

opentelemetry-otlp/examples/basic-otlp-http/Cargo.toml

+4-6
Original file line numberDiff line numberDiff line change
@@ -8,24 +8,22 @@ publish = false
88
[features]
99
default = ["reqwest"]
1010
reqwest = ["opentelemetry-otlp/reqwest-client"]
11-
hyper = ["dep:async-trait", "dep:http", "dep:http-body-util", "dep:hyper", "dep:hyper-util", "dep:opentelemetry-http", "dep:bytes"]
11+
hyper = ["opentelemetry-otlp/hyper-client"]
1212

1313

1414
[dependencies]
1515
once_cell = { workspace = true }
1616
opentelemetry = { path = "../../../opentelemetry" }
17-
opentelemetry_sdk = { path = "../../../opentelemetry-sdk", features = ["rt-tokio", "metrics", "logs"] }
18-
opentelemetry-http = { path = "../../../opentelemetry-http", optional = true }
19-
opentelemetry-otlp = { path = "../..", features = ["http-proto", "http-json", "reqwest-client", "logs"] }
17+
opentelemetry_sdk = { path = "../../../opentelemetry-sdk", features = ["rt-tokio", "metrics", "logs"]}
18+
opentelemetry-http = { path = "../../../opentelemetry-http", optional = true, default-features = false}
19+
opentelemetry-otlp = { path = "../..", features = ["http-proto", "http-json", "logs"] , default-features = false}
2020
opentelemetry-appender-tracing = { path = "../../../opentelemetry-appender-tracing", default-features = false}
2121
opentelemetry-semantic-conventions = { path = "../../../opentelemetry-semantic-conventions" }
2222

2323
async-trait = { workspace = true, optional = true }
2424
bytes = { workspace = true, optional = true }
2525
http = { workspace = true, optional = true }
2626
http-body-util = { workspace = true, optional = true }
27-
hyper = { workspace = true, features = ["client"], optional = true }
28-
hyper-util = { workspace = true, features = ["client-legacy"], optional = true }
2927
tokio = { workspace = true, features = ["full"] }
3028
tracing = { workspace = true, features = ["std"]}
3129
tracing-core = { workspace = true }

opentelemetry-otlp/examples/basic-otlp-http/src/hyper.rs

-49
This file was deleted.

opentelemetry-otlp/examples/basic-otlp-http/src/main.rs

+5-13
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
/// To use hyper as the HTTP client - cargo run --features="hyper" --no-default-features
12
use once_cell::sync::Lazy;
23
use opentelemetry::{
34
global,
@@ -23,12 +24,6 @@ use tracing::info;
2324
use tracing_subscriber::prelude::*;
2425
use tracing_subscriber::EnvFilter;
2526

26-
#[cfg(feature = "hyper")]
27-
use opentelemetry_otlp::WithHttpConfig;
28-
29-
#[cfg(feature = "hyper")]
30-
mod hyper;
31-
3227
static RESOURCE: Lazy<Resource> = Lazy::new(|| {
3328
Resource::new(vec![KeyValue::new(
3429
opentelemetry_semantic_conventions::resource::SERVICE_NAME,
@@ -37,15 +32,11 @@ static RESOURCE: Lazy<Resource> = Lazy::new(|| {
3732
});
3833

3934
fn init_logs() -> Result<sdklogs::LoggerProvider, opentelemetry::logs::LogError> {
40-
let exporter_builder = LogExporter::builder()
35+
let exporter = LogExporter::builder()
4136
.with_http()
4237
.with_endpoint("http://localhost:4318/v1/logs")
43-
.with_protocol(Protocol::HttpBinary);
44-
45-
#[cfg(feature = "hyper")]
46-
let exporter_builder = exporter_builder.with_http_client(hyper::HyperClient::default());
47-
48-
let exporter = exporter_builder.build()?;
38+
.with_protocol(Protocol::HttpBinary)
39+
.build()?;
4940

5041
Ok(LoggerProvider::builder()
5142
.with_batch_exporter(exporter, runtime::Tokio)
@@ -59,6 +50,7 @@ fn init_tracer_provider() -> Result<sdktrace::TracerProvider, TraceError> {
5950
.with_protocol(Protocol::HttpBinary) //can be changed to `Protocol::HttpJson` to export in JSON format
6051
.with_endpoint("http://localhost:4318/v1/traces")
6152
.build()?;
53+
6254
Ok(TracerProvider::builder()
6355
.with_batch_exporter(exporter, runtime::Tokio)
6456
.with_config(Config::default().with_resource(RESOURCE.clone()))

opentelemetry-otlp/src/exporter/http/mod.rs

+36-13
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,20 @@ mod logs;
3333
#[cfg(feature = "trace")]
3434
mod trace;
3535

36+
#[cfg(all(
37+
not(feature = "reqwest-client"),
38+
not(feature = "reqwest-blocking-client"),
39+
feature = "hyper-client"
40+
))]
41+
use opentelemetry_http::hyper::HyperClient;
42+
3643
/// Configuration of the http transport
3744
#[derive(Debug)]
3845
#[cfg_attr(
3946
all(
4047
not(feature = "reqwest-client"),
41-
not(feature = "reqwest-blocking-client")
48+
not(feature = "reqwest-blocking-client"),
49+
not(feature = "hyper-client")
4250
),
4351
derive(Default)
4452
)]
@@ -50,19 +58,36 @@ pub struct HttpConfig {
5058
headers: Option<HashMap<String, String>>,
5159
}
5260

53-
#[cfg(any(feature = "reqwest-blocking-client", feature = "reqwest-client",))]
61+
#[cfg(any(
62+
feature = "reqwest-blocking-client",
63+
feature = "reqwest-client",
64+
feature = "hyper-client"
65+
))]
5466
impl Default for HttpConfig {
5567
fn default() -> Self {
68+
#[cfg(feature = "reqwest-blocking-client")]
69+
let default_client =
70+
Some(Arc::new(reqwest::blocking::Client::new()) as Arc<dyn HttpClient>);
71+
#[cfg(all(not(feature = "reqwest-blocking-client"), feature = "reqwest-client"))]
72+
let default_client = Some(Arc::new(reqwest::Client::new()) as Arc<dyn HttpClient>);
73+
#[cfg(all(
74+
not(feature = "reqwest-client"),
75+
not(feature = "reqwest-blocking-client"),
76+
feature = "hyper-client"
77+
))]
78+
// TODO - support configuring custom connector and executor
79+
let default_client = Some(Arc::new(HyperClient::with_default_connector(
80+
Duration::from_secs(10),
81+
None,
82+
)) as Arc<dyn HttpClient>);
83+
#[cfg(all(
84+
not(feature = "reqwest-client"),
85+
not(feature = "reqwest-blocking-client"),
86+
not(feature = "hyper-client")
87+
))]
88+
let default_client = None;
5689
HttpConfig {
57-
#[cfg(feature = "reqwest-blocking-client")]
58-
client: Some(Arc::new(reqwest::blocking::Client::new())),
59-
#[cfg(all(not(feature = "reqwest-blocking-client"), feature = "reqwest-client"))]
60-
client: Some(Arc::new(reqwest::Client::new())),
61-
#[cfg(all(
62-
not(feature = "reqwest-client"),
63-
not(feature = "reqwest-blocking-client")
64-
))]
65-
client: None,
90+
client: default_client,
6691
headers: None,
6792
}
6893
}
@@ -140,13 +165,11 @@ impl HttpExporterBuilder {
140165
},
141166
None => self.exporter_config.timeout,
142167
};
143-
144168
let http_client = self
145169
.http_config
146170
.client
147171
.take()
148172
.ok_or(crate::Error::NoHttpClient)?;
149-
150173
#[allow(clippy::mutable_key_type)] // http headers are not mutated
151174
let mut headers: HashMap<HeaderName, HeaderValue> = self
152175
.http_config

opentelemetry-sdk/src/metrics/internal/exponential_histogram.rs

+1
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,7 @@ impl<T: Number> ExpoHistogram<T> {
352352
pub(crate) fn measure(&self, value: T, attrs: &[KeyValue]) {
353353
let f_value = value.into_float();
354354
// Ignore NaN and infinity.
355+
// Only makes sense if T is f64, maybe this could be no-op for other cases?
355356
if f_value.is_infinite() || f_value.is_nan() {
356357
return;
357358
}

0 commit comments

Comments
 (0)