@@ -34,6 +34,11 @@ mod tests {
3434 use serde_json:: json;
3535 use std:: time:: Duration ;
3636
37+ #[ cfg( feature = "_unstable-o12y" ) ]
38+ use google_cloud_test_utils:: test_layer:: TestLayer ;
39+ #[ cfg( feature = "_unstable-o12y" ) ]
40+ use opentelemetry_semantic_conventions:: trace:: HTTP_REQUEST_RESEND_COUNT ;
41+
3742 type Result < T > = std:: result:: Result < T , Box < dyn std:: error:: Error > > ;
3843
3944 #[ tokio:: test( flavor = "multi_thread" , worker_threads = 2 ) ]
@@ -106,6 +111,88 @@ mod tests {
106111 Ok ( ( ) )
107112 }
108113
114+ #[ cfg( feature = "_unstable-o12y" ) ]
115+ #[ tokio:: test( flavor = "multi_thread" , worker_threads = 2 ) ]
116+ async fn retry_loop_retry_success_with_tracing_on ( ) -> Result < ( ) > {
117+ let guard = TestLayer :: initialize ( ) ;
118+ // We create a server that will return two transient errors and then succeed.
119+ let server = start ( vec ! [ transient( ) , transient( ) , success( ) ] ) ;
120+ let endpoint = format ! ( "http://{}" , server. addr( ) ) ;
121+
122+ let mut config = test_config ( ) ;
123+ config. tracing = true ;
124+ let client = ReqwestClient :: new ( config, & endpoint) . await ?;
125+ let builder = client. builder ( reqwest:: Method :: GET , "/retry" . into ( ) ) ;
126+ let body = json ! ( { } ) ;
127+
128+ let options = {
129+ let mut options = RequestOptions :: default ( ) ;
130+ options. set_backoff_policy ( test_backoff ( ) ) ;
131+ options. set_idempotency ( true ) ;
132+ options
133+ } ;
134+ let response = client
135+ . execute :: < serde_json:: Value , serde_json:: Value > ( builder, Some ( body) , options)
136+ . await ;
137+ let response = response?. into_body ( ) ;
138+ assert_eq ! ( response, json!( { "status" : "done" } ) ) ;
139+
140+ let spans = TestLayer :: capture ( & guard) ;
141+ assert_eq ! (
142+ spans. len( ) ,
143+ 3 ,
144+ "Expected 3 spans for 3 attempts, got: {:?}" ,
145+ spans
146+ ) ;
147+
148+ // Span 0 (Initial Attempt)
149+ let span0 = & spans[ 0 ] ;
150+ assert_eq ! ( span0. name, "http_request" ) ;
151+ let attributes0 = & span0. attributes ;
152+
153+ assert ! (
154+ attributes0. get( HTTP_REQUEST_RESEND_COUNT ) . is_none( ) ,
155+ "Span 0: '{}' should not be present, got: {:?}, all attributes: {:?}" ,
156+ HTTP_REQUEST_RESEND_COUNT ,
157+ attributes0. get( HTTP_REQUEST_RESEND_COUNT ) ,
158+ attributes0
159+ ) ;
160+
161+ // Span 1 (Retry 1)
162+ let span1 = & spans[ 1 ] ;
163+ assert_eq ! ( span1. name, "http_request" ) ;
164+ let attributes1 = & span1. attributes ;
165+
166+ let expected_resend_count = "1" . to_string ( ) ;
167+ assert_eq ! (
168+ attributes1. get( HTTP_REQUEST_RESEND_COUNT ) ,
169+ Some ( & expected_resend_count) ,
170+ "Span 1: '{}' mismatch, expected: {:?}, got: {:?}, all attributes: {:?}" ,
171+ HTTP_REQUEST_RESEND_COUNT ,
172+ Some ( & expected_resend_count) ,
173+ attributes1. get( HTTP_REQUEST_RESEND_COUNT ) ,
174+ attributes1
175+ ) ;
176+
177+ // Span 2 (Retry 2 - Success)
178+ let span2 = & spans[ 2 ] ;
179+ assert_eq ! ( span2. name, "http_request" ) ;
180+ let attributes2 = & span2. attributes ;
181+
182+ let expected_resend_count = "2" . to_string ( ) ;
183+ assert_eq ! (
184+ attributes2. get( HTTP_REQUEST_RESEND_COUNT ) ,
185+ Some ( & expected_resend_count) ,
186+ "Span 2: '{}' mismatch, expected: {:?}, got: {:?}, all attributes: {:?}" ,
187+ HTTP_REQUEST_RESEND_COUNT ,
188+ Some ( & expected_resend_count) ,
189+ attributes2. get( HTTP_REQUEST_RESEND_COUNT ) ,
190+ attributes2
191+ ) ;
192+
193+ Ok ( ( ) )
194+ }
195+
109196 #[ tokio:: test( flavor = "multi_thread" , worker_threads = 2 ) ]
110197 async fn retry_loop_too_many_transients ( ) -> Result < ( ) > {
111198 // We create a server that will return N transient errors.
0 commit comments