@@ -132,6 +132,7 @@ pub(crate) fn record_intermediate_client_request(
132132 result : Result < & reqwest:: Response , & gax:: error:: Error > ,
133133 prior_attempt_count : u32 ,
134134 method : & http:: Method ,
135+ request_url : & reqwest:: Url ,
135136) {
136137 let span = Span :: current ( ) ;
137138 if span. is_disabled ( ) {
@@ -149,20 +150,29 @@ pub(crate) fn record_intermediate_client_request(
149150
150151 span. record ( otel_trace:: HTTP_REQUEST_METHOD , method. as_str ( ) ) ;
151152
153+ let final_url = match result {
154+ Ok ( response) => response. url ( ) ,
155+ Err ( _) => request_url,
156+ } ;
157+
158+ span. record (
159+ otel_trace:: SERVER_ADDRESS ,
160+ final_url
161+ . host_str ( )
162+ . map ( |h| h. trim_start_matches ( '[' ) . trim_end_matches ( ']' ) )
163+ . unwrap_or ( "" ) ,
164+ ) ;
165+ span. record (
166+ otel_trace:: SERVER_PORT ,
167+ final_url
168+ . port_or_known_default ( )
169+ . map ( |p| p as i64 )
170+ . unwrap_or ( 0 ) ,
171+ ) ;
172+ span. record ( otel_trace:: URL_FULL , final_url. as_str ( ) ) ;
173+
152174 match result {
153175 Ok ( response) => {
154- let url = response. url ( ) ;
155- span. record (
156- otel_trace:: SERVER_ADDRESS ,
157- url. host_str ( )
158- . map ( |h| h. trim_start_matches ( '[' ) . trim_end_matches ( ']' ) )
159- . unwrap_or ( "" ) ,
160- ) ;
161- span. record (
162- otel_trace:: SERVER_PORT ,
163- url. port_or_known_default ( ) . map ( |p| p as i64 ) . unwrap_or ( 0 ) ,
164- ) ;
165- span. record ( otel_trace:: URL_FULL , url. as_str ( ) ) ;
166176 span. record (
167177 otel_trace:: HTTP_RESPONSE_STATUS_CODE ,
168178 response. status ( ) . as_u16 ( ) as i64 ,
@@ -172,8 +182,6 @@ pub(crate) fn record_intermediate_client_request(
172182 if let Some ( status) = err. http_status_code ( ) {
173183 span. record ( otel_trace:: HTTP_RESPONSE_STATUS_CODE , status as i64 ) ;
174184 }
175- // For errors, we might not have the final URL if the request failed before sending.
176- // We rely on the initial URL set on the T3 span.
177185 }
178186 }
179187
@@ -540,12 +548,13 @@ mod tests {
540548 let span = create_client_request_span ( "test_span" , "test_method" , & TEST_INFO ) ;
541549 let _enter = span. enter ( ) ;
542550
551+ let url = "https://example.com/test" . parse :: < reqwest:: Url > ( ) . unwrap ( ) ;
543552 let response = http:: Response :: builder ( )
544553 . status ( StatusCode :: OK )
545554 . body ( "" )
546555 . unwrap ( ) ;
547556 let reqwest_response: reqwest:: Response = response. into ( ) ;
548- record_intermediate_client_request ( Ok ( & reqwest_response) , 1 , & Method :: GET ) ;
557+ record_intermediate_client_request ( Ok ( & reqwest_response) , 1 , & Method :: GET , & url ) ;
549558
550559 let captured = TestLayer :: capture ( & guard) ;
551560 assert_eq ! ( captured. len( ) , 1 , "captured spans: {:?}" , captured) ;
@@ -576,12 +585,13 @@ mod tests {
576585 ) ;
577586 let _enter = span. enter ( ) ;
578587
588+ let url = "https://example.com/test" . parse :: < reqwest:: Url > ( ) . unwrap ( ) ;
579589 let response = http:: Response :: builder ( )
580590 . status ( StatusCode :: OK )
581591 . body ( "" )
582592 . unwrap ( ) ;
583593 let reqwest_response: reqwest:: Response = response. into ( ) ;
584- record_intermediate_client_request ( Ok ( & reqwest_response) , 1 , & Method :: GET ) ;
594+ record_intermediate_client_request ( Ok ( & reqwest_response) , 1 , & Method :: GET , & url ) ;
585595
586596 let captured = TestLayer :: capture ( & guard) ;
587597 assert_eq ! ( captured. len( ) , 1 , "captured spans: {:?}" , captured) ;
@@ -598,9 +608,10 @@ mod tests {
598608 let span = create_client_request_span ( "test_span" , "test_method" , & TEST_INFO ) ;
599609 let _enter = span. enter ( ) ;
600610
611+ let url = "https://example.com/test" . parse :: < reqwest:: Url > ( ) . unwrap ( ) ;
601612 // Simulate a 404 error
602613 let error = gax:: error:: Error :: http ( 404 , http:: HeaderMap :: new ( ) , bytes:: Bytes :: new ( ) ) ;
603- record_intermediate_client_request ( Err ( & error) , 1 , & Method :: POST ) ;
614+ record_intermediate_client_request ( Err ( & error) , 1 , & Method :: POST , & url ) ;
604615
605616 let captured = TestLayer :: capture ( & guard) ;
606617 assert_eq ! ( captured. len( ) , 1 , "captured spans: {:?}" , captured) ;
@@ -618,5 +629,14 @@ mod tests {
618629 attributes. get( otel_trace:: HTTP_REQUEST_METHOD ) ,
619630 Some ( & "POST" . into( ) )
620631 ) ;
632+ // Verify URL attributes from fallback
633+ assert_eq ! (
634+ attributes. get( otel_trace:: URL_FULL ) ,
635+ Some ( & "https://example.com/test" . into( ) )
636+ ) ;
637+ assert_eq ! (
638+ attributes. get( otel_trace:: SERVER_ADDRESS ) ,
639+ Some ( & "example.com" . into( ) )
640+ ) ;
621641 }
622642}
0 commit comments