Skip to content

Commit d5c86d9

Browse files
[opentelemetry-otlp] adds an example HTTP exporter backed by Hyper (#1861)
Co-authored-by: Cijo Thomas <[email protected]>
1 parent 028d3e7 commit d5c86d9

File tree

4 files changed

+78
-16
lines changed

4 files changed

+78
-16
lines changed

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

Lines changed: 11 additions & 0 deletions
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

Lines changed: 8 additions & 0 deletions
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.
Lines changed: 45 additions & 0 deletions
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

Lines changed: 14 additions & 16 deletions
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)