@@ -12,11 +12,12 @@ use std::{fmt, result};
1212use axum:: extract:: MatchedPath ;
1313use futures_util:: ready;
1414use opentelemetry:: global:: { self , BoxedTracer } ;
15+ use opentelemetry:: metrics:: Meter ;
1516use opentelemetry:: metrics:: { Histogram , MeterProvider , UpDownCounter } ;
1617use opentelemetry:: trace:: { SpanKind , Status , TraceContextExt , Tracer , TracerProvider } ;
1718use opentelemetry:: Context as OtelContext ;
1819use opentelemetry:: KeyValue ;
19- use opentelemetry_sdk :: trace :: SdkTracerProvider ;
20+ use opentelemetry_http :: HeaderExtractor ;
2021use opentelemetry_semantic_conventions as semconv;
2122use pin_project_lite:: pin_project;
2223use tower_layer:: Layer ;
@@ -123,14 +124,11 @@ where
123124}
124125
125126/// State scoped to the entire middleware Layer.
126- ///
127- /// Holds metrics instruments.
128127struct 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
153153impl HTTPLayer {
@@ -164,8 +164,8 @@ impl Default for HTTPLayer {
164164}
165165
166166pub 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