2323import io .opentelemetry .api .trace .SpanKind ;
2424import io .opentelemetry .api .trace .StatusCode ;
2525import io .opentelemetry .api .trace .Tracer ;
26+ import io .opentelemetry .context .Scope ;
2627import io .opentelemetry .sdk .OpenTelemetrySdk ;
2728import io .opentelemetry .sdk .testing .exporter .InMemorySpanExporter ;
2829import io .opentelemetry .sdk .trace .ReadableSpan ;
4344import reactor .core .publisher .Mono ;
4445import reactor .test .StepVerifier ;
4546
47+ import java .time .Duration ;
4648import java .util .ArrayList ;
4749import java .util .Arrays ;
4850import java .util .HashMap ;
6264/**
6365 * Unit tests for {com.azure.core.implementation.http.policy.InstrumentationPolicy.
6466 */
67+ @ SuppressWarnings ("try" )
6568public class OpenTelemetryHttpPolicyTests {
6669
6770 private static final String X_MS_REQUEST_ID_1 = "response id 1" ;
@@ -85,7 +88,7 @@ public void setUp(TestInfo testInfo) {
8588
8689 @ Test
8790 public void openTelemetryHttpPolicyTest () {
88- // Start user parent span.
91+ // Start parent span.
8992 Span parentSpan = tracer .spanBuilder (SPAN_NAME ).startSpan ();
9093
9194 // Add parent span to tracingContext
@@ -95,8 +98,10 @@ public void openTelemetryHttpPolicyTest() {
9598 // Act
9699 HttpRequest request = new HttpRequest (HttpMethod .POST , "https://httpbin.org/hello?there#otel" );
97100 request .setHeader ("User-Agent" , "user-agent" );
98- HttpResponse response = createHttpPipeline (azTracer ).send (request , tracingContext ).block ();
99101
102+ try (Scope scope = parentSpan .makeCurrent ()) {
103+ createHttpPipeline (azTracer ).send (request , tracingContext ).block ();
104+ }
100105 // Assert
101106 List <SpanData > exportedSpans = exporter .getFinishedSpanItems ();
102107 // rest proxy span is not exported as global otel is not configured
@@ -150,10 +155,12 @@ public String getDescription() {
150155
151156 // Act
152157 HttpRequest request = new HttpRequest (HttpMethod .DELETE , "https://httpbin.org/hello?there#otel" );
153- HttpResponse response = createHttpPipeline (new OpenTelemetryTracer ("test" , null , null ,
158+ try (Scope scope = tracer .spanBuilder ("test" ).startSpan ().makeCurrent ()) {
159+ createHttpPipeline (new OpenTelemetryTracer ("test" , null , null ,
154160 new OpenTelemetryTracingOptions ().setProvider (providerWithSampler )))
155- .send (request ).block ();
156-
161+ .send (request )
162+ .block ();
163+ }
157164 // Assert
158165 List <SpanData > exportedSpans = exporter .getFinishedSpanItems ();
159166 assertEquals (0 , exportedSpans .size ());
@@ -162,33 +169,33 @@ public String getDescription() {
162169
163170 @ Test
164171 public void clientRequestIdIsStamped () {
165- HttpRequest request = new HttpRequest (HttpMethod .PUT , "https://httpbin.org/hello?there#otel" );
166- HttpResponse response = createHttpPipeline (azTracer , new RequestIdPolicy ()).send (request ).block ();
172+ try (Scope scope = tracer .spanBuilder ("test" ).startSpan ().makeCurrent ()) {
173+ HttpRequest request = new HttpRequest (HttpMethod .PUT , "https://httpbin.org/hello?there#otel" );
174+ HttpResponse response = createHttpPipeline (azTracer , new RequestIdPolicy ()).send (request ).block ();
167175
168- // Assert
169- List <SpanData > exportedSpans = exporter .getFinishedSpanItems ();
170- assertEquals (1 , exportedSpans .size ());
176+ // Assert
177+ List <SpanData > exportedSpans = exporter .getFinishedSpanItems ();
178+ assertEquals (1 , exportedSpans .size ());
171179
172- assertEquals ("HTTP PUT" , exportedSpans .get (0 ).getName ());
180+ assertEquals ("HTTP PUT" , exportedSpans .get (0 ).getName ());
173181
174- Map <String , Object > httpAttributes = getAttributes (exportedSpans .get (0 ));
175- assertEquals (5 , httpAttributes .size ());
182+ Map <String , Object > httpAttributes = getAttributes (exportedSpans .get (0 ));
183+ assertEquals (5 , httpAttributes .size ());
176184
177- assertEquals (response .getRequest ().getHeaders ().getValue ("x-ms-client-request-id" ), httpAttributes .get ("az.client_request_id" ));
178- assertEquals (X_MS_REQUEST_ID_1 , httpAttributes .get ("az.service_request_id" ));
185+ assertEquals (response .getRequest ().getHeaders ().getValue ("x-ms-client-request-id" ), httpAttributes .get ("az.client_request_id" ));
186+ assertEquals (X_MS_REQUEST_ID_1 , httpAttributes .get ("az.service_request_id" ));
179187
180- assertEquals ("https://httpbin.org/hello?there#otel" , httpAttributes .get ("http.url" ));
181- assertEquals ("PUT" , httpAttributes .get ("http.method" ));
182- assertEquals (Long .valueOf (RESPONSE_STATUS_CODE ), httpAttributes .get ("http.status_code" ));
188+ assertEquals ("https://httpbin.org/hello?there#otel" , httpAttributes .get ("http.url" ));
189+ assertEquals ("PUT" , httpAttributes .get ("http.method" ));
190+ assertEquals (Long .valueOf (RESPONSE_STATUS_CODE ), httpAttributes .get ("http.status_code" ));
191+ }
183192 }
184193
185194 @ Test
186195 public void everyTryIsTraced () {
187196 AtomicInteger attemptCount = new AtomicInteger ();
188197 AtomicReference <String > traceparentTry503 = new AtomicReference <>();
189198 AtomicReference <String > traceparentTry200 = new AtomicReference <>();
190- AtomicReference <Span > currentSpanTry503 = new AtomicReference <>();
191- AtomicReference <Span > currentSpanTry200 = new AtomicReference <>();
192199
193200 OpenTelemetryTracingOptions options = new OpenTelemetryTracingOptions ().setProvider (tracerProvider );
194201
@@ -205,12 +212,10 @@ public void everyTryIsTraced() {
205212 int count = attemptCount .getAndIncrement ();
206213 if (count == 0 ) {
207214 traceparentTry503 .set (request .getHeaders ().getValue ("traceparent" ));
208- currentSpanTry503 .set (Span .current ());
209215 headers .set ("x-ms-request-id" , X_MS_REQUEST_ID_1 );
210216 return Mono .just (new MockHttpResponse (request , 503 , headers ));
211217 } else if (count == 1 ) {
212218 traceparentTry200 .set (request .getHeaders ().getValue ("traceparent" ));
213- currentSpanTry200 .set (Span .current ());
214219 headers .set ("x-ms-request-id" , X_MS_REQUEST_ID_2 );
215220 return Mono .just (new MockHttpResponse (request , 200 , headers ));
216221 } else {
@@ -240,9 +245,6 @@ public void everyTryIsTraced() {
240245 assertEquals (traceparentTry503 .get (), String .format ("00-%s-%s-01" , try503 .getTraceId (), try503 .getSpanId ()));
241246 assertEquals (traceparentTry200 .get (), String .format ("00-%s-%s-01" , try200 .getTraceId (), try200 .getSpanId ()));
242247
243- assertEquals (currentSpanTry503 .get ().getSpanContext ().getSpanId (), try503 .getSpanId ());
244- assertEquals (currentSpanTry200 .get ().getSpanContext ().getSpanId (), try200 .getSpanId ());
245-
246248 assertEquals ("HTTP GET" , try503 .getName ());
247249 Map <String , Object > httpAttributes503 = getAttributes (try503 );
248250 assertEquals (5 , httpAttributes503 .size ());
@@ -370,6 +372,36 @@ public void timeoutIsTraced() {
370372 assertEquals (TimeoutException .class .getName (), events .get (0 ).getAttributes ().get (AttributeKey .stringKey ("exception.type" )));
371373 }
372374
375+ @ Test
376+ public void cancelIsTraced () {
377+ OpenTelemetryTracingOptions options = new OpenTelemetryTracingOptions ().setProvider (tracerProvider );
378+
379+ com .azure .core .util .tracing .Tracer azTracer = new OpenTelemetryTracer ("test" , null , null , options );
380+
381+ List <HttpPipelinePolicy > policies = new ArrayList <>(Arrays .asList (new RetryPolicy ()));
382+ HttpPolicyProviders .addAfterRetryPolicies (policies );
383+
384+ HttpPipeline pipeline = new HttpPipelineBuilder ()
385+ .policies (policies .toArray (new HttpPipelinePolicy [0 ]))
386+ .httpClient (request ->
387+ Mono .delay (Duration .ofSeconds (10 )).map (l -> new MockHttpResponse (request , 200 )))
388+ .tracer (azTracer )
389+ .build ();
390+
391+ pipeline .send (new HttpRequest (HttpMethod .GET , "http://localhost/hello" ), Context .NONE )
392+ .toFuture ()
393+ .cancel (true );
394+
395+ List <SpanData > exportedSpans = exporter .getFinishedSpanItems ();
396+ assertEquals (1 , exportedSpans .size ());
397+
398+ SpanData cancelled = exportedSpans .get (0 );
399+ Map <String , Object > httpAttributesTimeout = getAttributes (cancelled );
400+ assertNull (httpAttributesTimeout .get ("http.status_code" ));
401+ assertEquals (StatusCode .ERROR , cancelled .getStatus ().getStatusCode ());
402+ assertEquals ("cancel" , cancelled .getStatus ().getDescription ());
403+ }
404+
373405 private Map <String , Object > getAttributes (SpanData span ) {
374406 Map <String , Object > attributes = new HashMap <>();
375407 span .getAttributes ().forEach ((k , v ) -> attributes .put (k .getKey (), v ));
@@ -411,13 +443,10 @@ public Mono<HttpResponse> send(HttpRequest request) {
411443 HttpHeaders headers = new HttpHeaders ()
412444 .set ("x-ms-request-id" , X_MS_REQUEST_ID_1 );
413445
446+ // parent span
414447 SpanContext currentContext = Span .current ().getSpanContext ();
415- String expectedTraceparent = String .format ("00-%s-%s-%s" , currentContext .getTraceId (), currentContext .getSpanId (), currentContext .getTraceFlags ().toString ());
416- if (currentContext .isValid ()) {
417- assertEquals (expectedTraceparent , request .getHeaders ().getValue ("traceparent" ));
418- } else {
419- assertNull (request .getHeaders ().getValue ("traceparent" ));
420- }
448+ assertTrue (currentContext .isValid ());
449+ assertEquals (currentContext .getTraceId (), request .getHeaders ().getValue ("traceparent" ).substring (3 , 35 ));
421450
422451 return Mono .just (new MockHttpResponse (request , RESPONSE_STATUS_CODE , headers ));
423452 }
0 commit comments