Search in sources :

Example 11 with ExchangeFunction

use of org.springframework.web.reactive.function.client.ExchangeFunction in project spring-cloud-sleuth by spring-cloud.

the class TraceExchangeFilterFunction method filter.

@Override
public Mono<ClientResponse> filter(ClientRequest request, ExchangeFunction next) {
    final ClientRequest.Builder builder = ClientRequest.from(request);
    Mono<ClientResponse> exchange = Mono.defer(() -> next.exchange(builder.build())).cast(Object.class).onErrorResume(Mono::just).zipWith(Mono.subscriberContext()).flatMap(anyAndContext -> {
        Object any = anyAndContext.getT1();
        Span clientSpan = anyAndContext.getT2().get(CLIENT_SPAN_KEY);
        Mono<ClientResponse> continuation;
        final Tracer.SpanInScope ws = tracer().withSpanInScope(clientSpan);
        if (any instanceof Throwable) {
            continuation = Mono.error((Throwable) any);
        } else {
            continuation = Mono.just((ClientResponse) any);
        }
        return continuation.doAfterSuccessOrError((clientResponse, throwable1) -> {
            Throwable throwable = throwable1;
            if (clientResponse == null || clientResponse.statusCode() == null) {
                if (log.isDebugEnabled()) {
                    log.debug("No response was returned. Will close the span [" + clientSpan + "]");
                }
                handleReceive(clientSpan, ws, clientResponse, throwable);
                return;
            }
            boolean error = clientResponse.statusCode().is4xxClientError() || clientResponse.statusCode().is5xxServerError();
            if (error) {
                if (log.isDebugEnabled()) {
                    log.debug("Non positive status code was returned from the call. Will close the span [" + clientSpan + "]");
                }
                throwable = new RestClientException("Status code of the response is [" + clientResponse.statusCode().value() + "] and the reason is [" + clientResponse.statusCode().getReasonPhrase() + "]");
            }
            handleReceive(clientSpan, ws, clientResponse, throwable);
        });
    }).subscriberContext(c -> {
        if (log.isDebugEnabled()) {
            log.debug("Instrumenting WebClient call");
        }
        Span parent = c.getOrDefault(Span.class, null);
        Span clientSpan = handler().handleSend(injector(), builder, request, tracer().nextSpan());
        if (log.isDebugEnabled()) {
            log.debug("Created a client span for the WebClient " + clientSpan);
        }
        if (parent == null) {
            c = c.put(Span.class, clientSpan);
            if (log.isDebugEnabled()) {
                log.debug("Reactor Context got injected with the client span " + clientSpan);
            }
        }
        return c.put(CLIENT_SPAN_KEY, clientSpan);
    });
    return exchange;
}
Also used : ClientResponse(org.springframework.web.reactive.function.client.ClientResponse) RestClientException(org.springframework.web.client.RestClientException) HttpTracing(brave.http.HttpTracing) ClientResponse(org.springframework.web.reactive.function.client.ClientResponse) ExchangeFunction(org.springframework.web.reactive.function.client.ExchangeFunction) Tracer(brave.Tracer) Span(brave.Span) WebClient(org.springframework.web.reactive.function.client.WebClient) BeansException(org.springframework.beans.BeansException) Mono(reactor.core.publisher.Mono) TraceContext(brave.propagation.TraceContext) Consumer(java.util.function.Consumer) BeanPostProcessor(org.springframework.beans.factory.config.BeanPostProcessor) ClientRequest(org.springframework.web.reactive.function.client.ClientRequest) List(java.util.List) ExchangeFilterFunction(org.springframework.web.reactive.function.client.ExchangeFilterFunction) BeanFactory(org.springframework.beans.factory.BeanFactory) Propagation(brave.propagation.Propagation) HttpClientHandler(brave.http.HttpClientHandler) Log(org.apache.commons.logging.Log) LogFactory(org.apache.commons.logging.LogFactory) Mono(reactor.core.publisher.Mono) RestClientException(org.springframework.web.client.RestClientException) Span(brave.Span) ClientRequest(org.springframework.web.reactive.function.client.ClientRequest)

Example 12 with ExchangeFunction

use of org.springframework.web.reactive.function.client.ExchangeFunction in project spring-boot by spring-projects.

the class MetricsWebClientFilterFunctionTests method filterWhenExceptionAndRetryShouldNotAccumulateRecordTime.

@Test
void filterWhenExceptionAndRetryShouldNotAccumulateRecordTime() {
    ClientRequest request = ClientRequest.create(HttpMethod.GET, URI.create("https://example.com/projects/spring-boot")).build();
    ExchangeFunction exchange = (r) -> Mono.error(new IllegalArgumentException()).delaySubscription(Duration.ofMillis(1000)).cast(ClientResponse.class);
    this.filterFunction.filter(request, exchange).retry(1).onErrorResume(IllegalArgumentException.class, (t) -> Mono.empty()).block(Duration.ofSeconds(5));
    Timer timer = this.registry.get("http.client.requests").tags("method", "GET", "uri", "/projects/spring-boot", "status", "CLIENT_ERROR").timer();
    assertThat(timer.count()).isEqualTo(2);
    assertThat(timer.max(TimeUnit.MILLISECONDS)).isLessThan(2000);
}
Also used : BeforeEach(org.junit.jupiter.api.BeforeEach) SimpleMeterRegistry(io.micrometer.core.instrument.simple.SimpleMeterRegistry) StepVerifier(reactor.test.StepVerifier) AutoTimer(org.springframework.boot.actuate.metrics.AutoTimer) MockClock(io.micrometer.core.instrument.MockClock) Assertions.assertThat(org.assertj.core.api.Assertions.assertThat) WebClient(org.springframework.web.reactive.function.client.WebClient) ClientRequest(org.springframework.web.reactive.function.client.ClientRequest) Timer(io.micrometer.core.instrument.Timer) Assertions.assertThatThrownBy(org.assertj.core.api.Assertions.assertThatThrownBy) BDDMockito.given(org.mockito.BDDMockito.given) Duration(java.time.Duration) URI(java.net.URI) ClientResponse(org.springframework.web.reactive.function.client.ClientResponse) ExchangeFunction(org.springframework.web.reactive.function.client.ExchangeFunction) MeterNotFoundException(io.micrometer.core.instrument.search.MeterNotFoundException) SimpleConfig(io.micrometer.core.instrument.simple.SimpleConfig) HttpMethod(org.springframework.http.HttpMethod) IOException(java.io.IOException) Mono(reactor.core.publisher.Mono) TimeUnit(java.util.concurrent.TimeUnit) Test(org.junit.jupiter.api.Test) HttpStatus(org.springframework.http.HttpStatus) MeterRegistry(io.micrometer.core.instrument.MeterRegistry) Mockito.mock(org.mockito.Mockito.mock) AutoTimer(org.springframework.boot.actuate.metrics.AutoTimer) Timer(io.micrometer.core.instrument.Timer) ClientRequest(org.springframework.web.reactive.function.client.ClientRequest) ExchangeFunction(org.springframework.web.reactive.function.client.ExchangeFunction) Test(org.junit.jupiter.api.Test)

Aggregations

ExchangeFunction (org.springframework.web.reactive.function.client.ExchangeFunction)12 ClientRequest (org.springframework.web.reactive.function.client.ClientRequest)11 Mono (reactor.core.publisher.Mono)11 URI (java.net.URI)10 Duration (java.time.Duration)10 HttpMethod (org.springframework.http.HttpMethod)10 HttpStatus (org.springframework.http.HttpStatus)10 Assertions.assertThat (org.assertj.core.api.Assertions.assertThat)9 Test (org.junit.jupiter.api.Test)9 ClientResponse (org.springframework.web.reactive.function.client.ClientResponse)9 BeforeEach (org.junit.jupiter.api.BeforeEach)8 BDDMockito.given (org.mockito.BDDMockito.given)8 Mockito.mock (org.mockito.Mockito.mock)8 List (java.util.List)7 MockClientHttpRequest (org.springframework.mock.http.client.reactive.MockClientHttpRequest)7 ArrayList (java.util.ArrayList)6 StandardCharsets (java.nio.charset.StandardCharsets)5 Instant (java.time.Instant)5 Collections (java.util.Collections)5 HashMap (java.util.HashMap)5