Skip to content

Commit

Permalink
Support HTTP protocol and TLS for OpenTelemetry traces exporter (#6)
Browse files Browse the repository at this point in the history
This is a port of @hgiasac's PR in the other repository, which was lost
during migration. Apologies; this was my fault.

* Currently, the OTEL exporter can't connect to HTTPS endpoints due to
missing `tls` and `tls-roots` features. This PR enables them.
* By default, OTEL exporter shouldn't be enabled if `--otlp-endpoint` is
empty. Currently the exporter is always running.
* Users can switch to HTTP protocol with
`OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf`
* Upgrade the latest dependencies for `opentelemetry` packages.
* Allow configuring log level with `RUST_LOG` env variable.

Co-authored-by: Toan Nguyen <[email protected]>
  • Loading branch information
SamirTalwar and hgiasac authored Apr 22, 2024
1 parent 6158b1a commit 972dba6
Show file tree
Hide file tree
Showing 4 changed files with 193 additions and 42 deletions.
113 changes: 110 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ To enable tracing you must:
- set the SDK environment variable `OTEL_EXPORTER_OTLP_ENDPOINT`, or
- set the `tracing` environment variable `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT`.

The exporter uses gRPC protocol by default. To use HTTP protocol you must set `OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf`.

For additional service information you can:

- Set `OTEL_SERVICE_NAME` e.g. `ndc_hub_example`
Expand Down
2 changes: 1 addition & 1 deletion crates/sdk/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ http = "0.2"
mime = "0.3.17"
opentelemetry = "0.22.0"
opentelemetry-http = "0.11.0"
opentelemetry-otlp = { version = "0.15.0", features = ["reqwest-client"] }
opentelemetry-otlp = { version = "0.15.0", features = ["reqwest-client", "gzip-tonic", "tls", "tls-roots", "http-proto"] }
opentelemetry-semantic-conventions = "0.14.0"
opentelemetry_sdk = { version = "0.22.1", features = ["rt-tokio"] }
opentelemetry-zipkin = "0.20.0"
Expand Down
118 changes: 80 additions & 38 deletions crates/sdk/src/tracing.rs
Original file line number Diff line number Diff line change
@@ -1,60 +1,102 @@
use std::borrow::ToOwned;
use std::env;
use std::error::Error;
use std::time::Duration;

use axum::body::{Body, BoxBody};
use http::{Request, Response};
use opentelemetry::propagation::composite::TextMapCompositePropagator;
use opentelemetry_otlp::WithExportConfig;
use tracing::Span;
use opentelemetry_otlp::{SpanExporterBuilder, WithExportConfig};
use tracing::{Level, Span};
use tracing_opentelemetry::OpenTelemetrySpanExt;
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, EnvFilter};
use tracing_subscriber::layer::SubscriberExt;
use tracing_subscriber::util::SubscriberInitExt;

pub fn init_tracing(
service_name: Option<&str>,
otlp_endpoint: Option<&str>,
) -> Result<(), Box<dyn Error + Send + Sync>> {
opentelemetry::global::set_text_map_propagator(TextMapCompositePropagator::new(vec![
Box::new(opentelemetry_sdk::propagation::TraceContextPropagator::new()),
Box::new(opentelemetry_zipkin::Propagator::new()),
]));
let trace_endpoint = otlp_endpoint
.map(ToOwned::to_owned)
.or_else(|| env::var(opentelemetry_otlp::OTEL_EXPORTER_OTLP_TRACES_ENDPOINT).ok());

let tracer = opentelemetry_otlp::new_pipeline()
.tracing()
.with_exporter(opentelemetry_otlp::new_exporter().tonic().with_endpoint(
otlp_endpoint.unwrap_or(opentelemetry_otlp::OTEL_EXPORTER_OTLP_ENDPOINT_DEFAULT),
))
.with_trace_config(
opentelemetry_sdk::trace::config()
.with_resource(opentelemetry_sdk::Resource::new(vec![
opentelemetry::KeyValue::new(
opentelemetry_semantic_conventions::resource::SERVICE_NAME,
service_name.unwrap_or(env!("CARGO_PKG_NAME")).to_string(),
),
opentelemetry::KeyValue::new(
opentelemetry_semantic_conventions::resource::SERVICE_VERSION,
env!("CARGO_PKG_VERSION"),
),
]))
.with_sampler(opentelemetry_sdk::trace::Sampler::ParentBased(Box::new(
opentelemetry_sdk::trace::Sampler::AlwaysOn,
))),
)
.install_batch(opentelemetry_sdk::runtime::Tokio)?;

tracing_subscriber::registry()
let log_level = env::var("RUST_LOG").unwrap_or(Level::INFO.to_string());
let subscriber = tracing_subscriber::registry()
.with(
tracing_opentelemetry::layer()
.with_error_records_to_exceptions(true)
.with_tracer(tracer),
tracing_subscriber::EnvFilter::builder()
.parse(format!("{log_level},otel::tracing=trace,otel=debug"))?,
)
.with(EnvFilter::builder().parse("info,otel::tracing=trace,otel=debug")?)
.with(
tracing_subscriber::fmt::layer()
.json()
.with_timer(tracing_subscriber::fmt::time::time()),
)
.init();
);

match trace_endpoint {
// disable traces exporter if the endpoint is empty
None => subscriber.init(),
Some(endpoint) => {
opentelemetry::global::set_text_map_propagator(
opentelemetry::propagation::composite::TextMapCompositePropagator::new(vec![
Box::new(opentelemetry_sdk::propagation::TraceContextPropagator::new()),
Box::new(opentelemetry_zipkin::Propagator::new()),
]),
);

let service_name = service_name.unwrap_or(env!("CARGO_PKG_NAME"));

let exporter: SpanExporterBuilder =
match env::var(opentelemetry_otlp::OTEL_EXPORTER_OTLP_PROTOCOL) {
Ok(protocol) => match protocol.as_str() {
"grpc" => Ok(opentelemetry_otlp::new_exporter()
.tonic()
.with_endpoint(endpoint)
.into()),
"http/protobuf" => Ok(opentelemetry_otlp::new_exporter()
.http()
.with_endpoint(endpoint)
.into()),
invalid => Err(format!("invalid protocol: {invalid:?}")),
},
// the default exporter protocol is grpc
Err(env::VarError::NotPresent) => Ok(opentelemetry_otlp::new_exporter()
.tonic()
.with_endpoint(endpoint)
.into()),
Err(env::VarError::NotUnicode(os_str)) => {
Err(format!("invalid protocol: {os_str:?}"))
}
}?;

let tracer = opentelemetry_otlp::new_pipeline()
.tracing()
.with_exporter(exporter)
.with_trace_config(
opentelemetry_sdk::trace::config()
.with_resource(opentelemetry_sdk::Resource::new(vec![
opentelemetry::KeyValue::new(
opentelemetry_semantic_conventions::resource::SERVICE_NAME,
service_name.to_string(),
),
opentelemetry::KeyValue::new(
opentelemetry_semantic_conventions::resource::SERVICE_VERSION,
env!("CARGO_PKG_VERSION"),
),
]))
.with_sampler(opentelemetry_sdk::trace::Sampler::ParentBased(Box::new(
opentelemetry_sdk::trace::Sampler::AlwaysOn,
))),
)
.install_batch(opentelemetry_sdk::runtime::Tokio)?;

subscriber
.with(
tracing_opentelemetry::layer()
.with_error_records_to_exceptions(true)
.with_tracer(tracer),
)
.init();
}
};

Ok(())
}
Expand Down

0 comments on commit 972dba6

Please sign in to comment.