Skip to content

Commit

Permalink
[opentelemetry-otlp] adds an example HTTP exporter backed by Hyper (#…
Browse files Browse the repository at this point in the history
…1861)

Co-authored-by: Cijo Thomas <cijo.thomas@gmail.com>
  • Loading branch information
markdingram and cijothomas committed Jul 1, 2024
1 parent 028d3e7 commit d5c86d9
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 16 deletions.
11 changes: 11 additions & 0 deletions opentelemetry-otlp/examples/basic-otlp-http/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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 }
Expand Down
8 changes: 8 additions & 0 deletions opentelemetry-otlp/examples/basic-otlp-http/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
45 changes: 45 additions & 0 deletions opentelemetry-otlp/examples/basic-otlp-http/src/hyper.rs
Original file line number Diff line number Diff line change
@@ -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<C> {
inner: hyper::Client<C>,
}

impl Default for HyperClient<HttpConnector> {
fn default() -> Self {
Self {
inner: Client::new(),
}
}
}

impl<C> std::fmt::Debug for HyperClient<C> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("HyperClient")
.field("inner", &self.inner)
.finish()
}
}

#[async_trait]
impl<C: Connect + Clone + Send + Sync + 'static> HttpClient for HyperClient<C> {
async fn send(&self, request: Request<Vec<u8>>) -> Result<Response<Bytes>, 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))
}
}
30 changes: 14 additions & 16 deletions opentelemetry-otlp/examples/basic-otlp-http/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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},
Expand All @@ -18,45 +18,43 @@ use tracing_subscriber::EnvFilter;

use std::error::Error;

#[cfg(feature = "hyper")]
mod hyper;

static RESOURCE: Lazy<Resource> = Lazy::new(|| {
Resource::new(vec![KeyValue::new(
opentelemetry_semantic_conventions::resource::SERVICE_NAME,
"basic-otlp-example",
)])
});

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<sdklogs::LoggerProvider, opentelemetry::logs::LogError> {
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<sdktrace::TracerProvider, TraceError> {
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)
}

fn init_metrics() -> Result<opentelemetry_sdk::metrics::SdkMeterProvider, MetricsError> {
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()
}
Expand Down

0 comments on commit d5c86d9

Please sign in to comment.