@@ -89,7 +89,37 @@ macro_rules! root_span {
8989 let connection_info = $request. connection_info( ) ;
9090 let request_id = $crate:: root_span_macro:: private:: get_request_id( $request) ;
9191
92+ // Extract trace_id from incoming request headers (e.g. traceparent)
93+ // BEFORE creating the span, so it is available in on_new_span.
94+ let __otel_trace_id = $crate:: root_span_macro:: private:: extract_otel_trace_id( & $request) ;
95+
96+ // Two inner_span arms: one pre-populates trace_id when a remote parent
97+ // is found in the request headers; the other leaves it Empty for later.
9298 macro_rules! inner_span {
99+ ( $level: expr, trace_id = $tid: expr) => {
100+ $crate:: root_span_macro:: private:: tracing:: span!(
101+ $level,
102+ "HTTP request" ,
103+ http. method = %http_method,
104+ http. route = %http_route,
105+ http. flavor = %$crate:: root_span_macro:: private:: http_flavor( $request. version( ) ) ,
106+ http. scheme = %$crate:: root_span_macro:: private:: http_scheme( connection_info. scheme( ) ) ,
107+ http. host = %connection_info. host( ) ,
108+ http. client_ip = %$request. connection_info( ) . realip_remote_addr( ) . unwrap_or( "" ) ,
109+ http. user_agent = %user_agent,
110+ http. target = %$request. uri( ) . path_and_query( ) . map( |p| p. as_str( ) ) . unwrap_or( "" ) ,
111+ http. status_code = $crate:: root_span_macro:: private:: tracing:: field:: Empty ,
112+ otel. name = %format!( "{} {}" , http_method, http_route) ,
113+ otel. kind = "server" ,
114+ otel. status_code = $crate:: root_span_macro:: private:: tracing:: field:: Empty ,
115+ trace_id = %$tid,
116+ request_id = %request_id,
117+ exception. message = $crate:: root_span_macro:: private:: tracing:: field:: Empty ,
118+ // Not proper OpenTelemetry, but their terminology is fairly exception-centric
119+ exception. details = $crate:: root_span_macro:: private:: tracing:: field:: Empty ,
120+ $( $field) *
121+ )
122+ } ;
93123 ( $level: expr) => {
94124 $crate:: root_span_macro:: private:: tracing:: span!(
95125 $level,
@@ -115,13 +145,30 @@ macro_rules! root_span {
115145 )
116146 } ;
117147 }
118- let span = match $lvl {
119- $crate:: Level :: TRACE => inner_span!( $crate:: Level :: TRACE ) ,
120- $crate:: Level :: DEBUG => inner_span!( $crate:: Level :: DEBUG ) ,
121- $crate:: Level :: INFO => inner_span!( $crate:: Level :: INFO ) ,
122- $crate:: Level :: WARN => inner_span!( $crate:: Level :: WARN ) ,
123- $crate:: Level :: ERROR => inner_span!( $crate:: Level :: ERROR ) ,
124- } ;
148+
149+ macro_rules! make_span {
150+ ( $lvl_value: expr, $trace_id: expr) => {
151+ if let Some ( ref __tid) = $trace_id {
152+ match $lvl_value {
153+ $crate:: Level :: TRACE => inner_span!( $crate:: Level :: TRACE , trace_id = __tid) ,
154+ $crate:: Level :: DEBUG => inner_span!( $crate:: Level :: DEBUG , trace_id = __tid) ,
155+ $crate:: Level :: INFO => inner_span!( $crate:: Level :: INFO , trace_id = __tid) ,
156+ $crate:: Level :: WARN => inner_span!( $crate:: Level :: WARN , trace_id = __tid) ,
157+ $crate:: Level :: ERROR => inner_span!( $crate:: Level :: ERROR , trace_id = __tid) ,
158+ }
159+ } else {
160+ match $lvl_value {
161+ $crate:: Level :: TRACE => inner_span!( $crate:: Level :: TRACE ) ,
162+ $crate:: Level :: DEBUG => inner_span!( $crate:: Level :: DEBUG ) ,
163+ $crate:: Level :: INFO => inner_span!( $crate:: Level :: INFO ) ,
164+ $crate:: Level :: WARN => inner_span!( $crate:: Level :: WARN ) ,
165+ $crate:: Level :: ERROR => inner_span!( $crate:: Level :: ERROR ) ,
166+ }
167+ }
168+ } ;
169+ }
170+
171+ let span = make_span!( $lvl, __otel_trace_id) ;
125172 std:: mem:: drop( connection_info) ;
126173
127174 // Previously, this line was instrumented with an opentelemetry-specific feature
@@ -152,6 +199,59 @@ pub mod private {
152199
153200 use crate :: RequestId ;
154201
202+ #[ doc( hidden) ]
203+ #[ allow( unused_variables) ]
204+ pub fn extract_otel_trace_id ( req : & ServiceRequest ) -> Option < String > {
205+ #[ cfg( any(
206+ feature = "opentelemetry_0_13" ,
207+ feature = "opentelemetry_0_14" ,
208+ feature = "opentelemetry_0_15" ,
209+ feature = "opentelemetry_0_16" ,
210+ feature = "opentelemetry_0_17" ,
211+ feature = "opentelemetry_0_18" ,
212+ feature = "opentelemetry_0_19" ,
213+ feature = "opentelemetry_0_20" ,
214+ feature = "opentelemetry_0_21" ,
215+ feature = "opentelemetry_0_22" ,
216+ feature = "opentelemetry_0_23" ,
217+ feature = "opentelemetry_0_24" ,
218+ feature = "opentelemetry_0_25" ,
219+ feature = "opentelemetry_0_26" ,
220+ feature = "opentelemetry_0_27" ,
221+ feature = "opentelemetry_0_28" ,
222+ feature = "opentelemetry_0_29" ,
223+ feature = "opentelemetry_0_30" ,
224+ feature = "opentelemetry_0_31" ,
225+ ) ) ]
226+ {
227+ crate :: otel:: extract_trace_id ( req)
228+ }
229+ #[ cfg( not( any(
230+ feature = "opentelemetry_0_13" ,
231+ feature = "opentelemetry_0_14" ,
232+ feature = "opentelemetry_0_15" ,
233+ feature = "opentelemetry_0_16" ,
234+ feature = "opentelemetry_0_17" ,
235+ feature = "opentelemetry_0_18" ,
236+ feature = "opentelemetry_0_19" ,
237+ feature = "opentelemetry_0_20" ,
238+ feature = "opentelemetry_0_21" ,
239+ feature = "opentelemetry_0_22" ,
240+ feature = "opentelemetry_0_23" ,
241+ feature = "opentelemetry_0_24" ,
242+ feature = "opentelemetry_0_25" ,
243+ feature = "opentelemetry_0_26" ,
244+ feature = "opentelemetry_0_27" ,
245+ feature = "opentelemetry_0_28" ,
246+ feature = "opentelemetry_0_29" ,
247+ feature = "opentelemetry_0_30" ,
248+ feature = "opentelemetry_0_31" ,
249+ ) ) ) ]
250+ {
251+ None
252+ }
253+ }
254+
155255 #[ doc( hidden) ]
156256 // We need to allow unused variables because the function
157257 // body is empty if the user of the library chose not to activate
0 commit comments