@Override public void process(HttpResponse response, HttpContext context) { // See if there's a subspan passed to us from the request interceptor. Span spanToClose = (Span) context.getAttribute(SPAN_TO_CLOSE_HTTP_CONTEXT_ATTR_KEY); if (spanToClose != null) { // There was a subspan. Finalize and close it. try { // Handle response/error tagging and final span name. // The request should be found in the context attributes - try to extract it from there. // We have no access to any error, so we pass null for the error arg. HttpRequest request = null; Object requestRawObj = context.getAttribute(HttpCoreContext.HTTP_REQUEST); if (requestRawObj instanceof HttpRequest) { request = (HttpRequest) requestRawObj; } tagAndNamingStrategy.handleResponseTaggingAndFinalSpanName( spanToClose, request, response, null, tagAndNamingAdapter ); } finally { // Span.close() contains the logic we want - if the spanToClose was an overall span (new trace) // then tracer.completeRequestSpan() will be called, otherwise it's a subspan and // tracer.completeSubSpan() will be called. spanToClose.close(); } } }
@Override public void run() { Span span = Tracer.getInstance().getCurrentSpan(); //noinspection TryFinallyCanBeTryWithResources try { // Add the tags from the response. tagAndNamingStrategy.handleResponseTaggingAndFinalSpanName( span, request, response, error, tagAndNamingAdapter ); } finally { // Span.close() contains the logic we want - if the spanAroundCall was an overall span // (new trace) then tracer.completeRequestSpan() will be called, otherwise it's // a subspan and tracer.completeSubSpan() will be called. span.close(); } } },
@Override public void run() { Span span = Tracer.getInstance().getCurrentSpan(); //noinspection TryFinallyCanBeTryWithResources try { // Add the tags from the response. tagAndNamingStrategy.handleResponseTaggingAndFinalSpanName( span, request, response, error, tagAndNamingAdapter ); } finally { // Span.close() contains the logic we want - if the spanAroundCall was an overall span // (new trace) then tracer.completeRequestSpan() will be called, otherwise it's // a subspan and tracer.completeSubSpan() will be called. span.close(); } } },
@Test public void process_response_closes_span_no_matter_what() { // given Span spanMock = mock(Span.class); httpContext = spy(httpContext); httpContext.setAttribute(SPAN_TO_CLOSE_HTTP_CONTEXT_ATTR_KEY, spanMock); RuntimeException expectedEx = new RuntimeException("boom"); doThrow(expectedEx).when(httpContext).getAttribute(HttpCoreContext.HTTP_REQUEST); // when Throwable ex = catchThrowable(() -> interceptor.process(responseMock, httpContext)); // then assertThat(ex).isSameAs(expectedEx); verify(httpContext).getAttribute(HttpCoreContext.HTTP_REQUEST); verify(spanMock).close(); }
spanAroundCall.close();
spanAroundCall.close();
); verify(spanMock).close();
@Test public void close_completes_the_span_as_expected_overall_request_span() { // given Span overallSpan = Tracer.getInstance().startRequestWithRootSpan("root"); assertThat(Tracer.getInstance().getCurrentSpan()).isSameAs(overallSpan); assertThat(overallSpan.isCompleted()).isFalse(); // when overallSpan.close(); // then assertThat(overallSpan.isCompleted()).isTrue(); assertThat(Tracer.getInstance().getCurrentSpan()).isNull(); }
@Test public void close_completes_the_span_as_expected_subspan() { // given Span parentSpan = Tracer.getInstance().startRequestWithRootSpan("root"); Span subspan = Tracer.getInstance().startSubSpan("subspan", SpanPurpose.LOCAL_ONLY); assertThat(Tracer.getInstance().getCurrentSpan()).isSameAs(subspan); assertThat(subspan.isCompleted()).isFalse(); // when subspan.close(); // then assertThat(subspan.isCompleted()).isTrue(); assertThat(Tracer.getInstance().getCurrentSpan()).isSameAs(parentSpan); }
spanAroundCall.close();
parent.close();
spanAroundCall.close();
spanAroundCall.close();
@Test public void close_does_nothing_if_span_is_already_completed() { // given Span rootSpan = Tracer.getInstance().startRequestWithRootSpan("root"); Span subspan = Tracer.getInstance().startSubSpan("subspan", SpanPurpose.LOCAL_ONLY); Tracer.getInstance().completeSubSpan(); assertThat(subspan.isCompleted()).isTrue(); assertThat(rootSpan.isCompleted()).isFalse(); assertThat(Tracer.getInstance().getCurrentSpan()).isSameAs(rootSpan); assertThat(Tracer.getInstance().getCurrentSpanStackCopy()).isEqualTo(singletonList(rootSpan)); // when subspan.close(); // then assertThat(rootSpan.isCompleted()).isFalse(); assertThat(Tracer.getInstance().getCurrentSpan()).isSameAs(rootSpan); assertThat(Tracer.getInstance().getCurrentSpanStackCopy()).isEqualTo(singletonList(rootSpan)); }
parent.close();
parent.close();
parent.close();
invalidSpan.close();