Skip to content

Commit 5974fed

Browse files
committed
extract parent span
1 parent eaf22d3 commit 5974fed

File tree

2 files changed

+40
-38
lines changed

2 files changed

+40
-38
lines changed

opentelemetry-instrumentation-tower/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ futures-util = { version = "0.3", default-features = false }
2222
http = { version = "1", features = ["std"], default-features = false }
2323
http-body = { version = "1", default-features = false }
2424
opentelemetry = { workspace = true, features = ["futures", "metrics", "trace"] }
25-
opentelemetry_sdk = { workspace = true, features = ["trace"] }
25+
opentelemetry-http = "0.31"
2626
opentelemetry-semantic-conventions = { workspace = true, features = ["semconv_experimental"] }
2727
pin-project-lite = { version = "0.2", default-features = false }
2828
tower-service = { version = "0.3", default-features = false }

opentelemetry-instrumentation-tower/src/lib.rs

Lines changed: 39 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,12 @@ use std::{fmt, result};
1212
use axum::extract::MatchedPath;
1313
use futures_util::ready;
1414
use opentelemetry::global::{self, BoxedTracer};
15+
use opentelemetry::metrics::Meter;
1516
use opentelemetry::metrics::{Histogram, MeterProvider, UpDownCounter};
1617
use opentelemetry::trace::{SpanKind, Status, TraceContextExt, Tracer, TracerProvider};
1718
use opentelemetry::Context as OtelContext;
1819
use opentelemetry::KeyValue;
19-
use opentelemetry_sdk::trace::SdkTracerProvider;
20+
use opentelemetry_http::HeaderExtractor;
2021
use opentelemetry_semantic_conventions as semconv;
2122
use pin_project_lite::pin_project;
2223
use tower_layer::Layer;
@@ -123,14 +124,11 @@ where
123124
}
124125

125126
/// State scoped to the entire middleware Layer.
126-
///
127-
/// Holds metrics instruments.
128127
struct HTTPLayerState {
129128
pub server_request_duration: Histogram<f64>,
130129
pub server_active_requests: UpDownCounter<i64>,
131130
pub server_request_body_size: Histogram<u64>,
132131
pub server_response_body_size: Histogram<u64>,
133-
pub tracer_provider: Option<SdkTracerProvider>,
134132
}
135133

136134
#[derive(Clone)]
@@ -140,6 +138,7 @@ pub struct HTTPService<S, ReqExt = NoOpExtractor, ResExt = NoOpExtractor> {
140138
request_extractor: ReqExt,
141139
response_extractor: ResExt,
142140
inner_service: S,
141+
tracer: Arc<BoxedTracer>,
143142
}
144143

145144
#[derive(Clone)]
@@ -148,6 +147,7 @@ pub struct HTTPLayer<ReqExt = NoOpExtractor, ResExt = NoOpExtractor> {
148147
state: Arc<HTTPLayerState>,
149148
request_extractor: ReqExt,
150149
response_extractor: ResExt,
150+
tracer: Arc<BoxedTracer>,
151151
}
152152

153153
impl HTTPLayer {
@@ -164,8 +164,8 @@ impl Default for HTTPLayer {
164164
}
165165

166166
pub struct HTTPLayerBuilder<ReqExt = NoOpExtractor, ResExt = NoOpExtractor> {
167-
tracer_provider: Option<SdkTracerProvider>,
168-
meter_provider: Option<Box<dyn MeterProvider + Send + Sync>>,
167+
tracer_provider: Option<BoxedTracer>,
168+
meter: Option<Meter>,
169169
req_dur_bounds: Option<Vec<f64>>,
170170
request_extractor: ReqExt,
171171
response_extractor: ResExt,
@@ -211,7 +211,7 @@ impl HTTPLayerBuilder {
211211
pub fn builder() -> Self {
212212
HTTPLayerBuilder {
213213
tracer_provider: None,
214-
meter_provider: None,
214+
meter: None,
215215
req_dur_bounds: Some(LIBRARY_DEFAULT_HTTP_SERVER_DURATION_BOUNDARIES.to_vec()),
216216
request_extractor: NoOpExtractor,
217217
response_extractor: NoOpExtractor,
@@ -229,7 +229,7 @@ impl<ReqExt, ResExt> HTTPLayerBuilder<ReqExt, ResExt> {
229229
NewReqExt: RequestAttributeExtractor<B>,
230230
{
231231
HTTPLayerBuilder {
232-
meter_provider: self.meter_provider,
232+
meter: self.meter,
233233
tracer_provider: self.tracer_provider,
234234
req_dur_bounds: self.req_dur_bounds,
235235
request_extractor: extractor,
@@ -246,7 +246,7 @@ impl<ReqExt, ResExt> HTTPLayerBuilder<ReqExt, ResExt> {
246246
NewResExt: ResponseAttributeExtractor<B>,
247247
{
248248
HTTPLayerBuilder {
249-
meter_provider: self.meter_provider,
249+
meter: self.meter,
250250
tracer_provider: self.tracer_provider,
251251
req_dur_bounds: self.req_dur_bounds,
252252
request_extractor: self.request_extractor,
@@ -281,14 +281,20 @@ impl<ReqExt, ResExt> HTTPLayerBuilder<ReqExt, ResExt> {
281281
.req_dur_bounds
282282
.unwrap_or_else(|| LIBRARY_DEFAULT_HTTP_SERVER_DURATION_BOUNDARIES.to_vec());
283283

284+
let tracer: BoxedTracer = self
285+
.tracer_provider
286+
.unwrap_or_else(|| global::tracer("opentelemetry-instrumentation-tower"));
287+
let tracer = Arc::new(tracer);
288+
289+
let meter: Meter = self
290+
.meter
291+
.unwrap_or_else(|| global::meter("opentelemetry-instrumentation-tower"));
292+
284293
Ok(HTTPLayer {
285-
state: Arc::from(Self::make_state(
286-
self.meter_provider,
287-
self.tracer_provider,
288-
req_dur_bounds,
289-
)),
294+
state: Arc::from(Self::make_state(meter, req_dur_bounds)),
290295
request_extractor: self.request_extractor,
291296
response_extractor: self.response_extractor,
297+
tracer: tracer,
292298
})
293299
}
294300

@@ -303,26 +309,22 @@ impl<ReqExt, ResExt> HTTPLayerBuilder<ReqExt, ResExt> {
303309
where
304310
M: MeterProvider + Send + Sync + 'static,
305311
{
306-
self.meter_provider = Some(Box::new(provider));
312+
self.meter = Some(provider.meter("opentelemetry-intrumentation-tower"));
307313
self
308314
}
309315

310316
/// Set a meter provider to use for creating a meter.
311317
/// If none is specified, the global provider is used.
312-
pub fn with_tracer_provider(mut self, provider: SdkTracerProvider) -> Self {
313-
self.tracer_provider = Some(provider);
318+
pub fn with_tracer_provider<T>(mut self, provider: T) -> Self
319+
where
320+
T: TracerProvider + Send + Sync + 'static,
321+
{
322+
self.tracer_provider =
323+
Some(Box::new(provider.tracer("opentelemetry-intrumentation-tower")) as BoxedTracer);
314324
self
315325
}
316326

317-
fn make_state(
318-
meter_provider: Option<Box<dyn MeterProvider + Send + Sync>>,
319-
tracer_provider: Option<SdkTracerProvider>,
320-
req_dur_bounds: Vec<f64>,
321-
) -> HTTPLayerState {
322-
let meter = match meter_provider {
323-
Some(provider) => provider.meter("opentelemetry-instrumentation-tower"),
324-
None => global::meter("opentelemetry-instrumentation-tower"),
325-
};
327+
fn make_state(meter: Meter, req_dur_bounds: Vec<f64>) -> HTTPLayerState {
326328
HTTPLayerState {
327329
server_request_duration: meter
328330
.f64_histogram(Cow::from(HTTP_SERVER_DURATION_METRIC))
@@ -345,7 +347,6 @@ impl<ReqExt, ResExt> HTTPLayerBuilder<ReqExt, ResExt> {
345347
.with_description("Size of HTTP server response bodies.")
346348
.with_unit(HTTP_SERVER_RESPONSE_BODY_SIZE_UNIT)
347349
.build(),
348-
tracer_provider,
349350
}
350351
}
351352
}
@@ -363,6 +364,7 @@ where
363364
request_extractor: self.request_extractor.clone(),
364365
response_extractor: self.response_extractor.clone(),
365366
inner_service: service,
367+
tracer: self.tracer.clone(),
366368
}
367369
}
368370
}
@@ -450,7 +452,11 @@ where
450452
// Extract custom request attributes
451453
let custom_request_attributes = self.request_extractor.extract_attributes(&req);
452454

453-
// Start tracing span
455+
// Extract the context from the incoming request headers
456+
let parent_cx = global::get_text_map_propagator(|propagator| {
457+
propagator.extract(&HeaderExtractor(req.headers()))
458+
});
459+
454460
let mut span_attributes = vec![
455461
KeyValue::new(semconv::trace::HTTP_REQUEST_METHOD, method.clone()),
456462
url_scheme_kv.clone(),
@@ -473,18 +479,12 @@ where
473479

474480
let span_name = format!("{} {}", method, req.uri().path());
475481

476-
let tracer = match &self.state.tracer_provider {
477-
Some(tp) => {
478-
BoxedTracer::new(Box::new(tp.tracer("opentelemetry-instrumentation-tower")))
479-
}
480-
None => global::tracer("opentelemetry-instrumentation-tower"),
481-
};
482-
483-
let span = tracer
482+
let span = self
483+
.tracer
484484
.span_builder(span_name)
485485
.with_kind(SpanKind::Server)
486486
.with_attributes(span_attributes)
487-
.start(&tracer);
487+
.start_with_context(self.tracer.as_ref(), &parent_cx);
488488

489489
let cx = OtelContext::current_with_span(span);
490490

@@ -618,7 +618,9 @@ mod tests {
618618
use super::*;
619619

620620
use http::{Request, Response, StatusCode};
621+
use opentelemetry::global::ObjectSafeTracerProvider;
621622
use opentelemetry::trace::{FutureExt, TraceContextExt, Tracer};
623+
use opentelemetry::InstrumentationScope;
622624
use opentelemetry_sdk::metrics::SdkMeterProvider;
623625
use opentelemetry_sdk::metrics::{
624626
data::{AggregatedMetrics, MetricData},

0 commit comments

Comments
 (0)