Skip to content

Commit 9bd6162

Browse files
committed
[opentelemetry-otlp] basic-otlp-http example - adds Hyper feature
Resolves open-telemetry#1659
1 parent 3e49f23 commit 9bd6162

File tree

4 files changed

+78
-16
lines changed

4 files changed

+78
-16
lines changed

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

+11
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,25 @@ edition = "2021"
55
license = "Apache-2.0"
66
publish = false
77

8+
[features]
9+
default = ["reqwest"]
10+
reqwest = ["opentelemetry-otlp/reqwest-client"]
11+
hyper = ["dep:async-trait", "dep:http", "dep:hyper", "dep:opentelemetry-http", "dep:bytes"]
12+
13+
814
[dependencies]
915
once_cell = { workspace = true }
1016
opentelemetry = { path = "../../../opentelemetry" }
1117
opentelemetry_sdk = { path = "../../../opentelemetry-sdk", features = ["rt-tokio", "metrics", "logs"] }
18+
opentelemetry-http = { path = "../../../opentelemetry-http", optional = true }
1219
opentelemetry-otlp = { path = "../..", features = ["http-proto", "reqwest-client", "logs"] }
1320
opentelemetry-appender-tracing = { path = "../../../opentelemetry-appender-tracing", default-features = false}
1421
opentelemetry-semantic-conventions = { path = "../../../opentelemetry-semantic-conventions" }
1522

23+
async-trait = { workspace = true, optional = true }
24+
bytes = { workspace = true, optional = true }
25+
http = { workspace = true, optional = true }
26+
hyper = { workspace = true, features = ["client"], optional = true }
1627
tokio = { workspace = true, features = ["full"] }
1728
tracing = { workspace = true, features = ["std"]}
1829
tracing-core = { workspace = true }

opentelemetry-otlp/examples/basic-otlp-http/README.md

+8
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,14 @@ Run the app which exports logs, metrics and traces via OTLP to the collector
5252
cargo run
5353
```
5454

55+
56+
By default the app will use a `reqwest` client to send. A hyper 0.14 client can be used with the `hyper` feature enabled
57+
58+
```shell
59+
cargo run --no-default-features --features=hyper
60+
```
61+
62+
5563
## View results
5664

5765
You should be able to see something similar below with different time and ID in the same console that docker runs.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
use async_trait::async_trait;
2+
use bytes::Bytes;
3+
use http::{Request, Response};
4+
use hyper::{
5+
client::{connect::Connect, HttpConnector},
6+
Body, Client,
7+
};
8+
use opentelemetry_http::{HttpClient, HttpError, ResponseExt};
9+
10+
pub struct HyperClient<C> {
11+
inner: hyper::Client<C>,
12+
}
13+
14+
impl Default for HyperClient<HttpConnector> {
15+
fn default() -> Self {
16+
Self {
17+
inner: Client::new(),
18+
}
19+
}
20+
}
21+
22+
impl<C> std::fmt::Debug for HyperClient<C> {
23+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
24+
f.debug_struct("HyperClient")
25+
.field("inner", &self.inner)
26+
.finish()
27+
}
28+
}
29+
30+
#[async_trait]
31+
impl<C: Connect + Clone + Send + Sync + 'static> HttpClient for HyperClient<C> {
32+
async fn send(&self, request: Request<Vec<u8>>) -> Result<Response<Bytes>, HttpError> {
33+
let request = request.map(Body::from);
34+
35+
let (parts, body) = self
36+
.inner
37+
.request(request)
38+
.await?
39+
.error_for_status()?
40+
.into_parts();
41+
let body = hyper::body::to_bytes(body).await?;
42+
43+
Ok(Response::from_parts(parts, body))
44+
}
45+
}

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

+14-16
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use opentelemetry::{
66
Key, KeyValue,
77
};
88
use opentelemetry_appender_tracing::layer::OpenTelemetryTracingBridge;
9-
use opentelemetry_otlp::WithExportConfig;
9+
use opentelemetry_otlp::{HttpExporterBuilder, WithExportConfig};
1010
use opentelemetry_sdk::trace::{self as sdktrace, Config};
1111
use opentelemetry_sdk::{
1212
logs::{self as sdklogs},
@@ -18,45 +18,43 @@ use tracing_subscriber::EnvFilter;
1818

1919
use std::error::Error;
2020

21+
#[cfg(feature = "hyper")]
22+
mod hyper;
23+
2124
static RESOURCE: Lazy<Resource> = Lazy::new(|| {
2225
Resource::new(vec![KeyValue::new(
2326
opentelemetry_semantic_conventions::resource::SERVICE_NAME,
2427
"basic-otlp-example",
2528
)])
2629
});
2730

31+
fn http_exporter() -> HttpExporterBuilder {
32+
let exporter = opentelemetry_otlp::new_exporter().http();
33+
#[cfg(feature = "hyper")]
34+
let exporter = exporter.with_http_client(hyper::HyperClient::default());
35+
exporter
36+
}
37+
2838
fn init_logs() -> Result<sdklogs::LoggerProvider, opentelemetry::logs::LogError> {
2939
opentelemetry_otlp::new_pipeline()
3040
.logging()
3141
.with_resource(RESOURCE.clone())
32-
.with_exporter(
33-
opentelemetry_otlp::new_exporter()
34-
.http()
35-
.with_endpoint("http://localhost:4318/v1/logs"),
36-
)
42+
.with_exporter(http_exporter().with_endpoint("http://localhost:4318/v1/logs"))
3743
.install_batch(opentelemetry_sdk::runtime::Tokio)
3844
}
3945

4046
fn init_tracer_provider() -> Result<sdktrace::TracerProvider, TraceError> {
4147
opentelemetry_otlp::new_pipeline()
4248
.tracing()
43-
.with_exporter(
44-
opentelemetry_otlp::new_exporter()
45-
.http()
46-
.with_endpoint("http://localhost:4318/v1/traces"),
47-
)
49+
.with_exporter(http_exporter().with_endpoint("http://localhost:4318/v1/traces"))
4850
.with_trace_config(Config::default().with_resource(RESOURCE.clone()))
4951
.install_batch(opentelemetry_sdk::runtime::Tokio)
5052
}
5153

5254
fn init_metrics() -> Result<opentelemetry_sdk::metrics::SdkMeterProvider, MetricsError> {
5355
opentelemetry_otlp::new_pipeline()
5456
.metrics(opentelemetry_sdk::runtime::Tokio)
55-
.with_exporter(
56-
opentelemetry_otlp::new_exporter()
57-
.http()
58-
.with_endpoint("http://localhost:4318/v1/metrics"),
59-
)
57+
.with_exporter(http_exporter().with_endpoint("http://localhost:4318/v1/metrics"))
6058
.with_resource(RESOURCE.clone())
6159
.build()
6260
}

0 commit comments

Comments
 (0)