add traceparent to http headers
This commit is contained in:
Generated
+2
@@ -5940,6 +5940,8 @@ dependencies = [
|
||||
"nym-http-api-common",
|
||||
"nym-network-defaults",
|
||||
"once_cell",
|
||||
"opentelemetry",
|
||||
"opentelemetry_sdk",
|
||||
"reqwest 0.12.24",
|
||||
"serde",
|
||||
"serde_json",
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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:?}"
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user