WingtipsSpringWebfluxExchangeFilterFunction implements ExchangeFilterFunction { protected @NotNull Mono<ClientResponse> propagateTracingHeadersAndExecute( @NotNull ClientRequest request, @NotNull ExchangeFunction next, @Nullable TracingState tracingStateForReqAttrsAndMonoContext ) { ClientRequest.Builder requestWithTracingHeadersBuilder = ClientRequest.from(request); HttpRequestTracingUtils.propagateTracingHeaders( requestWithTracingHeadersBuilder::header, Tracer.getInstance().getCurrentSpan() ); if (tracingStateForReqAttrsAndMonoContext != null) { requestWithTracingHeadersBuilder.attribute(TracingState.class.getName(), tracingStateForReqAttrsAndMonoContext); } return next.exchange(requestWithTracingHeadersBuilder.build()) .subscriberContext( c -> (tracingStateForReqAttrsAndMonoContext == null) ? c : subscriberContextWithTracingInfo(c, tracingStateForReqAttrsAndMonoContext) ); } 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; }
@DataProvider(value = { "true | true", "true | false", "false | true", "false | false" }, splitBy = "\\|") @Test public void propagateTracingHeadersAndExecute_works_as_expected( boolean reqAttrAndMonoContextTracingStateIsNull, boolean propagationSpanHasParent ) { Tracer.getInstance().startRequestWithRootSpan("fooRootSpan"); Span expectedPropagationSpan = (propagationSpanHasParent) ? Tracer.getInstance().startSubSpan("fooSubspan", SpanPurpose.LOCAL_ONLY) : Tracer.getInstance().getCurrentSpan(); TracingState expectedTracingStateForReqAttrsAndMonoContext = (reqAttrAndMonoContextTracingStateIsNull) ? null : TracingState.getCurrentThreadTracingState(); Mono<ClientResponse> result = filterSpy.propagateTracingHeadersAndExecute( request, nextExchangeFunctionMock, expectedTracingStateForReqAttrsAndMonoContext ); StepVerifier .create(result) .expectAccessibleContext() .assertThat( c -> assertThat(tracingStateFromContext(c)).isEqualTo(expectedTracingStateForReqAttrsAndMonoContext) ) .then() .expectNext(responseMock) .expectComplete() .verify(); ArgumentCaptor<ClientRequest> filterChainRequestCaptor = ArgumentCaptor.forClass(ClientRequest.class); verify(nextExchangeFunctionMock).exchange(filterChainRequestCaptor.capture()); ClientRequest filterChainRequest = filterChainRequestCaptor.getValue(); verifyExpectedTraceHeaders(filterChainRequest.headers(), expectedPropagationSpan); assertThat(filterChainRequest.attribute(TracingState.class.getName())) .isEqualTo(Optional.ofNullable(expectedTracingStateForReqAttrsAndMonoContext)); }