add traceparent to http headers

This commit is contained in:
Floriane TUERNAL SABOTINOV
2025-09-30 12:30:00 +02:00
parent 60cde66451
commit 4116bb321a
5 changed files with 50 additions and 6 deletions
Generated
+2
View File
@@ -5940,6 +5940,8 @@ dependencies = [
"nym-http-api-common",
"nym-network-defaults",
"once_cell",
"opentelemetry",
"opentelemetry_sdk",
"reqwest 0.12.24",
"serde",
"serde_json",
+15 -3
View File
@@ -1,8 +1,7 @@
use opentelemetry::{Context, TraceFlags};
use opentelemetry::propagation::{Injector, Extractor, TextMapPropagator};
use opentelemetry::trace::{SpanContext, TraceContextExt, TraceId};
use opentelemetry_sdk::propagation::TraceContextPropagator;
use opentelemetry_sdk::trace::IdGenerator;
use opentelemetry_sdk::{propagation::TraceContextPropagator, trace::IdGenerator};
use tracing_opentelemetry::OpenTelemetrySpanExt;
use std::collections::HashMap;
@@ -19,15 +18,24 @@ impl ContextCarrier {
}
pub fn new_with_data(data: HashMap<String, String>) -> Self {
if data.is_empty() {
return ContextCarrier::new_empty();
}
ContextCarrier { data }
}
pub fn new_with_current_context(context: Context) -> Self {
let propagator = TraceContextPropagator::new();
let mut carrier = ContextCarrier::new_empty();
let propagator = TraceContextPropagator::new();
propagator.inject_context(&context, &mut carrier);
carrier
}
pub fn iter(&self) -> impl Iterator<Item = (&String, &String)> {
self.data.iter()
}
pub fn from_map(data: HashMap<String, String>) -> Self {
ContextCarrier { data }
}
@@ -46,6 +54,10 @@ impl ContextCarrier {
}
})
}
pub fn extract_traceparent(&self) -> Option<String> {
self.get("traceparent").map(|s| s.to_string())
}
}
impl Injector for ContextCarrier {
+6 -1
View File
@@ -11,9 +11,12 @@ license.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[features]
default=["tunneling"]
# TODO: Remove otel from default before release
# Opentelemetry should remain an opt-in for debug purposes only
default=["tunneling", "otel"]
tunneling=[]
network-defaults = ["dep:nym-network-defaults"]
otel = ["nym-bin-common/otel", "opentelemetry", "opentelemetry_sdk"]
debug-inventory = ["nym-http-api-client-macro/debug-inventory"]
[dependencies]
@@ -24,6 +27,8 @@ reqwest = { workspace = true, features = ["json", "gzip", "deflate", "brotli", "
http.workspace = true
url = { workspace = true }
once_cell = { workspace = true }
opentelemetry = { workspace = true, optional = true }
opentelemetry_sdk = { workspace = true, optional = true }
serde = { workspace = true }
serde_json = { workspace = true }
serde_yaml = { workspace = true}
+18
View File
@@ -986,6 +986,24 @@ impl ApiClientCore for Client {
self.apply_hosts_to_req(&mut req);
// if opentelemetry is activated add the current trace context to the request
// TODO featurize opentelemetry
use opentelemetry::Context;
use opentelemetry::propagation::TextMapPropagator;
use opentelemetry_sdk::propagation::TraceContextPropagator;
use nym_bin_common::opentelemetry::context::ContextCarrier;
let context = Context::current();
let propagator = TraceContextPropagator::new();
let mut carrier = ContextCarrier::new_empty();
propagator.inject_context(&context, &mut carrier);
if let Some(traceparent) = carrier.extract_traceparent() {
if let Ok(header_value) = HeaderValue::from_str(&traceparent) {
req.headers_mut()
.insert("traceparent", header_value);
}
}
let mut rb = RequestBuilder::from_parts(self.reqwest_client.clone(), req);
rb = rb
@@ -56,6 +56,13 @@ async fn log_request(
let host = header_map(request.headers().get(HOST), "Unknown Host".to_string());
// Extract traceparent from headers if it exists
let traceparent = request
.headers()
.get("traceparent")
.and_then(|h| h.to_str().ok())
.map(|s| s.to_string());
let start = Instant::now();
// run request through all middleware, incl. extractors
let res = next.run(request).await;
@@ -82,10 +89,10 @@ async fn log_request(
match level {
LogLevel::Debug => debug!(
"[{addr} -> {host}] {method} '{uri}': {print_status} {time_taken} {agent_str}: {agent}"
"[{addr} -> {host}] {method} '{uri}': {print_status} {time_taken} {agent_str}: {agent} traceparent: {traceparent:?}"
),
LogLevel::Info => info!(
"[{addr} -> {host}] {method} '{uri}': {print_status} {time_taken} {agent_str}: {agent}"
"[{addr} -> {host}] {method} '{uri}': {print_status} {time_taken} {agent_str}: {agent} traceparent: {traceparent:?}"
),
}