@Test public void completeSubspanAttachedToCurrentThread_completes_span_even_if_highly_improbable_exception_occurs() { Span rootSpan = Tracer.getInstance().startRequestWithRootSpan("fooRootSpan"); Span currentSpan = Tracer.getInstance().startSubSpan("fooSubspan", SpanPurpose.LOCAL_ONLY); RuntimeException improbableException = new RuntimeException("Intentional test exception"); @SuppressWarnings("unchecked") Pair<String, String> explodingTag = mock(Pair.class); doThrow(improbableException).when(explodingTag).getKey(); Throwable ex = catchThrowable( () -> WingtipsSpringWebfluxExchangeFilterFunction.completeSubspanAttachedToCurrentThread( request, responseMock, mock(Throwable.class), tagAndNamingStrategy, tagAndNamingAdapterMock, explodingTag ) ); assertThat(ex).isSameAs(improbableException); assertThat(currentSpan.isCompleted()).isTrue(); assertThat(spanRecorder.completedSpans).isEqualTo(singletonList(currentSpan)); assertThat(Tracer.getInstance().getCurrentSpan()).isEqualTo(rootSpan); }
@SafeVarargs protected static void completeSubspanAttachedToCurrentThread( @NotNull ClientRequest request, @Nullable ClientResponse response, @Nullable Throwable error, @NotNull HttpTagAndSpanNamingStrategy<ClientRequest, ClientResponse> tagAndNamingStrategy, @NotNull HttpTagAndSpanNamingAdapter<ClientRequest, ClientResponse> tagAndNamingAdapter, Pair<String, String>... extraCustomTags ) { Span span = Tracer.getInstance().getCurrentSpan(); if (span == null) { return; } if (span.isCompleted()) { return; } try { if (extraCustomTags != null) { for (Pair<String, String> tag : extraCustomTags) { span.putTag(tag.getKey(), tag.getValue()); } } tagAndNamingStrategy.handleResponseTaggingAndFinalSpanName( span, request, response, error, tagAndNamingAdapter ); } finally { span.close(); } }
WingtipsSpringWebfluxExchangeFilterFunction implements ExchangeFilterFunction { @SafeVarargs protected static void completeSubspanAttachedToCurrentThread( @NotNull ClientRequest request, @Nullable ClientResponse response, @Nullable Throwable error, @NotNull HttpTagAndSpanNamingStrategy<ClientRequest, ClientResponse> tagAndNamingStrategy, @NotNull HttpTagAndSpanNamingAdapter<ClientRequest, ClientResponse> tagAndNamingAdapter, Pair<String, String>... extraCustomTags ) { Span span = Tracer.getInstance().getCurrentSpan(); if (span == null) { return; } if (span.isCompleted()) { return; } try { if (extraCustomTags != null) { for (Pair<String, String> tag : extraCustomTags) { span.putTag(tag.getKey(), tag.getValue()); } } tagAndNamingStrategy.handleResponseTaggingAndFinalSpanName( span, request, response, error, tagAndNamingAdapter ); } finally { span.close(); } } }
WingtipsSpringWebfluxExchangeFilterFunction implements ExchangeFilterFunction { @SafeVarargs protected static void completeSubspanAttachedToCurrentThread( @NotNull ClientRequest request, @Nullable ClientResponse response, @Nullable Throwable error, @NotNull HttpTagAndSpanNamingStrategy<ClientRequest, ClientResponse> tagAndNamingStrategy, @NotNull HttpTagAndSpanNamingAdapter<ClientRequest, ClientResponse> tagAndNamingAdapter, Pair<String, String>... extraCustomTags ) { Span span = Tracer.getInstance().getCurrentSpan(); if (span == null) { return; } if (span.isCompleted()) { return; } try { if (extraCustomTags != null) { for (Pair<String, String> tag : extraCustomTags) { span.putTag(tag.getKey(), tag.getValue()); } } tagAndNamingStrategy.handleResponseTaggingAndFinalSpanName( span, request, response, error, tagAndNamingAdapter ); } finally { span.close(); } } WingtipsSpringWebfluxExchangeFilterFunction();  WingtipsSpringWebfluxExchangeFilterFunction(boolean surroundCallsWithSubspan); @SuppressWarnings("ConstantConditions")  WingtipsSpringWebfluxExchangeFilterFunction(
        boolean surroundCallsWithSubspan,
        @NotNull HttpTagAndSpanNamingStrategy<ClientRequest, ClientResponse> tagAndNamingStrategy,
        @NotNull HttpTagAndSpanNamingAdapter<ClientRequest, ClientResponse> tagAndNamingAdapter
    ); }
WingtipsSpringWebfluxExchangeFilterFunction implements ExchangeFilterFunction { @SafeVarargs protected static void completeSubspanAttachedToCurrentThread( @NotNull ClientRequest request, @Nullable ClientResponse response, @Nullable Throwable error, @NotNull HttpTagAndSpanNamingStrategy<ClientRequest, ClientResponse> tagAndNamingStrategy, @NotNull HttpTagAndSpanNamingAdapter<ClientRequest, ClientResponse> tagAndNamingAdapter, Pair<String, String>... extraCustomTags ) { Span span = Tracer.getInstance().getCurrentSpan(); if (span == null) { return; } if (span.isCompleted()) { return; } try { if (extraCustomTags != null) { for (Pair<String, String> tag : extraCustomTags) { span.putTag(tag.getKey(), tag.getValue()); } } tagAndNamingStrategy.handleResponseTaggingAndFinalSpanName( span, request, response, error, tagAndNamingAdapter ); } finally { span.close(); } } WingtipsSpringWebfluxExchangeFilterFunction();  WingtipsSpringWebfluxExchangeFilterFunction(boolean surroundCallsWithSubspan); @SuppressWarnings("ConstantConditions")  WingtipsSpringWebfluxExchangeFilterFunction(
        boolean surroundCallsWithSubspan,
        @NotNull HttpTagAndSpanNamingStrategy<ClientRequest, ClientResponse> tagAndNamingStrategy,
        @NotNull HttpTagAndSpanNamingAdapter<ClientRequest, ClientResponse> tagAndNamingAdapter
    ); @Override @NotNull Mono<ClientResponse> filter(
        @NotNull ClientRequest request, @NotNull ExchangeFunction next
    ); }
WingtipsSpringWebfluxExchangeFilterFunction implements ExchangeFilterFunction { @SafeVarargs protected static void completeSubspanAttachedToCurrentThread( @NotNull ClientRequest request, @Nullable ClientResponse response, @Nullable Throwable error, @NotNull HttpTagAndSpanNamingStrategy<ClientRequest, ClientResponse> tagAndNamingStrategy, @NotNull HttpTagAndSpanNamingAdapter<ClientRequest, ClientResponse> tagAndNamingAdapter, Pair<String, String>... extraCustomTags ) { Span span = Tracer.getInstance().getCurrentSpan(); if (span == null) { return; } if (span.isCompleted()) { return; } try { if (extraCustomTags != null) { for (Pair<String, String> tag : extraCustomTags) { span.putTag(tag.getKey(), tag.getValue()); } } tagAndNamingStrategy.handleResponseTaggingAndFinalSpanName( span, request, response, error, tagAndNamingAdapter ); } finally { span.close(); } } WingtipsSpringWebfluxExchangeFilterFunction();  WingtipsSpringWebfluxExchangeFilterFunction(boolean surroundCallsWithSubspan); @SuppressWarnings("ConstantConditions")  WingtipsSpringWebfluxExchangeFilterFunction(
        boolean surroundCallsWithSubspan,
        @NotNull HttpTagAndSpanNamingStrategy<ClientRequest, ClientResponse> tagAndNamingStrategy,
        @NotNull HttpTagAndSpanNamingAdapter<ClientRequest, ClientResponse> tagAndNamingAdapter
    ); @Override @NotNull Mono<ClientResponse> filter(
        @NotNull ClientRequest request, @NotNull ExchangeFunction next
    ); static final @NotNull WingtipsSpringWebfluxExchangeFilterFunction DEFAULT_IMPL; }