Search in sources :

Example 56 with Span

use of com.nike.wingtips.Span in project riposte by Nike-Inc.

the class AsyncHttpClientHelper method executeAsyncHttpRequest.

/**
 * Executes the given request asynchronously, handling the response with the given responseHandlerFunction, and
 * returns a {@link CompletableFuture} that represents the result of executing the
 * responseHandlerFunction on the downstream response. Any error anywhere along the way will cause the returned
 * future to be completed with {@link CompletableFuture#completeExceptionally(Throwable)}.
 * <p/>
 * <b>Distributed Tracing and MDC for the downstream call:</b> The given {@code distributedTraceStackForCall} and
 * {@code mdcContextForCall} arguments are used to setup distributed trace and MDC info for the downstream call so
 * that the callback will be performed with that data attached to whatever thread the callback is done on.
 */
public <O> CompletableFuture<O> executeAsyncHttpRequest(RequestBuilderWrapper requestBuilderWrapper, AsyncResponseHandler<O> responseHandlerFunction, Deque<Span> distributedTraceStackForCall, Map<String, String> mdcContextForCall) {
    CompletableFuture<O> completableFutureResponse = new CompletableFuture<>();
    try {
        Optional<ManualModeTask<Response>> circuitBreakerManualTask = getCircuitBreaker(requestBuilderWrapper).map(CircuitBreaker::newManualModeTask);
        // If we have a circuit breaker, give it a chance to throw an exception if the circuit is open/tripped
        circuitBreakerManualTask.ifPresent(ManualModeTask::throwExceptionIfCircuitBreakerIsOpen);
        // Setup the async completion handler for the call.
        AsyncCompletionHandlerWithTracingAndMdcSupport<O> asyncCompletionHandler = new AsyncCompletionHandlerWithTracingAndMdcSupport<>(completableFutureResponse, responseHandlerFunction, performSubSpanAroundDownstreamCalls, requestBuilderWrapper, circuitBreakerManualTask, distributedTraceStackForCall, mdcContextForCall, spanNamingAndTaggingStrategy);
        // Add distributed trace headers to the downstream call if we have a span.
        Span spanForCall = asyncCompletionHandler.getSpanForCall();
        if (spanForCall != null) {
            HttpRequestTracingUtils.propagateTracingHeaders((headerKey, headerValue) -> {
                if (headerValue != null) {
                    requestBuilderWrapper.requestBuilder.setHeader(headerKey, headerValue);
                }
            }, spanForCall);
        }
        // Add span tags if we're doing a subspan around the call.
        if (performSubSpanAroundDownstreamCalls && spanForCall != null) {
            spanNamingAndTaggingStrategy.handleRequestTagging(spanForCall, requestBuilderWrapper);
        }
        // Execute the downstream call. The completableFutureResponse will be completed or completed exceptionally
        // depending on the result of the call.
        requestBuilderWrapper.requestBuilder.execute(asyncCompletionHandler);
    } catch (Throwable t) {
        // normal when the circuit breaker associated with this request has been tripped.
        if (!(t instanceof CircuitBreakerOpenException)) {
            logger.error("An error occurred while trying to set up an async HTTP call for method {} and URL {}. " + "The CompletableFuture will be instantly failed with this error", requestBuilderWrapper.httpMethod, requestBuilderWrapper.url, t);
        }
        completableFutureResponse.completeExceptionally(t);
    }
    return completableFutureResponse;
}
Also used : CompletableFuture(java.util.concurrent.CompletableFuture) CircuitBreaker(com.nike.fastbreak.CircuitBreaker) ManualModeTask(com.nike.fastbreak.CircuitBreaker.ManualModeTask) Span(com.nike.wingtips.Span) CircuitBreakerOpenException(com.nike.fastbreak.exception.CircuitBreakerOpenException)

Example 57 with Span

use of com.nike.wingtips.Span in project riposte by Nike-Inc.

the class AsyncHttpClientHelper method executeAsyncHttpRequest.

/**
 * Executes the given request asynchronously, handling the response with the given responseHandlerFunction, and
 * returns a {@link CompletableFuture} that represents the result of executing the
 * responseHandlerFunction on the downstream response. Any error anywhere along the way will cause the returned
 * future to be completed with {@link CompletableFuture#completeExceptionally(Throwable)}.
 * <p/>
 * NOTE: This is a helper method for calling {@link #executeAsyncHttpRequest(RequestBuilderWrapper,
 * AsyncResponseHandler, java.util.Deque, java.util.Map)} that uses {@link
 * ChannelAttributes#getHttpProcessingStateForChannel(ChannelHandlerContext)} to extract the {@link
 * HttpProcessingState} from the given ctx argument, and then grabs {@link
 * HttpProcessingState#getDistributedTraceStack()} and {@link HttpProcessingState#getLoggerMdcContextMap()} to use
 * as the distributed trace stack and MDC info for the downstream call.
 */
public <O> CompletableFuture<O> executeAsyncHttpRequest(RequestBuilderWrapper requestBuilderWrapper, AsyncResponseHandler<O> responseHandlerFunction, ChannelHandlerContext ctx) {
    HttpProcessingState state = ChannelAttributes.getHttpProcessingStateForChannel(ctx).get();
    if (state == null)
        throw new IllegalStateException("state cannot be null");
    Map<String, String> mdcContextMap = state.getLoggerMdcContextMap();
    Deque<Span> distributedTraceStack = state.getDistributedTraceStack();
    requestBuilderWrapper.setCtx(ctx);
    return executeAsyncHttpRequest(requestBuilderWrapper, responseHandlerFunction, distributedTraceStack, mdcContextMap);
}
Also used : HttpProcessingState(com.nike.riposte.server.http.HttpProcessingState) Span(com.nike.wingtips.Span)

Example 58 with Span

use of com.nike.wingtips.Span in project riposte by Nike-Inc.

the class DefaultAsyncHttpClientHelperSpanNamingAndTaggingStrategyTest method beforeMethod.

@Before
public void beforeMethod() {
    initialSpanNameFromStrategy = new AtomicReference<>("span-name-from-strategy-" + UUID.randomUUID().toString());
    strategyInitialSpanNameMethodCalled = new AtomicBoolean(false);
    strategyRequestTaggingMethodCalled = new AtomicBoolean(false);
    strategyResponseTaggingAndFinalSpanNameMethodCalled = new AtomicBoolean(false);
    strategyInitialSpanNameArgs = new AtomicReference<>(null);
    strategyRequestTaggingArgs = new AtomicReference<>(null);
    strategyResponseTaggingArgs = new AtomicReference<>(null);
    wingtipsStrategy = new ArgCapturingHttpTagAndSpanNamingStrategy<>(initialSpanNameFromStrategy, strategyInitialSpanNameMethodCalled, strategyRequestTaggingMethodCalled, strategyResponseTaggingAndFinalSpanNameMethodCalled, strategyInitialSpanNameArgs, strategyRequestTaggingArgs, strategyResponseTaggingArgs);
    wingtipsAdapterMock = mock(HttpTagAndSpanNamingAdapter.class);
    impl = new DefaultAsyncHttpClientHelperSpanNamingAndTaggingStrategy(wingtipsStrategy, wingtipsAdapterMock);
    requestMock = mock(RequestBuilderWrapper.class);
    responseMock = mock(Response.class);
    errorMock = mock(Throwable.class);
    spanMock = mock(Span.class);
}
Also used : Response(com.ning.http.client.Response) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) Assertions.catchThrowable(org.assertj.core.api.Assertions.catchThrowable) HttpTagAndSpanNamingAdapter(com.nike.wingtips.tags.HttpTagAndSpanNamingAdapter) Span(com.nike.wingtips.Span) Before(org.junit.Before)

Example 59 with Span

use of com.nike.wingtips.Span in project riposte by Nike-Inc.

the class DefaultAsyncHttpClientHelperSpanNamingAndTaggingStrategyTest method doChangeSpanName_changes_span_name_as_expected.

@DataProvider(value = { "null           |   false", "               |   false", "[whitespace]   |   false", "fooNewName     |   true" }, splitBy = "\\|")
@Test
public void doChangeSpanName_changes_span_name_as_expected(String newName, boolean expectNameToBeChanged) {
    // given
    if ("[whitespace]".equals(newName)) {
        newName = "  \r\n\t  ";
    }
    String initialSpanName = UUID.randomUUID().toString();
    Span span = Span.newBuilder(initialSpanName, Span.SpanPurpose.CLIENT).build();
    String expectedSpanName = (expectNameToBeChanged) ? newName : initialSpanName;
    // when
    impl.doChangeSpanName(span, newName);
    // then
    assertThat(span.getSpanName()).isEqualTo(expectedSpanName);
}
Also used : Span(com.nike.wingtips.Span) DataProvider(com.tngtech.java.junit.dataprovider.DataProvider) Test(org.junit.Test)

Example 60 with Span

use of com.nike.wingtips.Span in project riposte by Nike-Inc.

the class AsyncCompletionHandlerWithTracingAndMdcSupport method onCompleted.

@Override
public Response onCompleted(Response response) {
    Pair<Deque<Span>, Map<String, String>> originalThreadInfo = null;
    try {
        // Link up the distributed tracing and MDC information to the current thread
        originalThreadInfo = linkTracingAndMdcToCurrentThread(distributedTraceStackToUse, mdcContextToUse);
        // Notify the circuit breaker of an event.
        try {
            circuitBreakerManualTask.ifPresent(cb -> cb.handleEvent(response));
        } catch (Throwable t) {
            logger.error("Circuit breaker threw an exception during handleEvent. This should never happen and means the " + "CircuitBreaker is malfunctioning. Ignoring exception.", t);
        }
        // If a subspan was started for the downstream call, it should now be completed
        if (performSubSpanAroundDownstreamCalls) {
            Span spanAroundCall = Tracer.getInstance().getCurrentSpan();
            // Handle the final span naming and response tagging.
            tagAndNamingStrategy.handleResponseTaggingAndFinalSpanName(spanAroundCall, rbwCopyWithHttpMethodAndUrlOnly, response, null);
            // The Span.close() method will do the right thing whether or not this is an overall request span or
            // subspan.
            spanAroundCall.close();
        }
        // and we should not do any more processing here.
        if (completableFutureResponse.isDone())
            return response;
        // completableFutureResponse with.
        try {
            O responseInfo = responseHandlerFunction.handleResponse(response);
            completableFutureResponse.complete(responseInfo);
        } catch (Throwable throwable) {
            // responseHandlerFunction threw an error. Complete completableFutureResponse exceptionally.
            completableFutureResponse.completeExceptionally(throwable);
        }
        return response;
    } finally {
        AsyncNettyHelper.unlinkTracingAndMdcFromCurrentThread(originalThreadInfo);
    }
}
Also used : Deque(java.util.Deque) Map(java.util.Map) Span(com.nike.wingtips.Span)

Aggregations

Span (com.nike.wingtips.Span)103 Test (org.junit.Test)73 DataProvider (com.tngtech.java.junit.dataprovider.DataProvider)41 Map (java.util.Map)26 Deque (java.util.Deque)24 Assertions.catchThrowable (org.assertj.core.api.Assertions.catchThrowable)20 CompletableFuture (java.util.concurrent.CompletableFuture)18 HttpProcessingState (com.nike.riposte.server.http.HttpProcessingState)13 ArgumentMatchers.anyString (org.mockito.ArgumentMatchers.anyString)12 HashMap (java.util.HashMap)10 HttpRequest (io.netty.handler.codec.http.HttpRequest)9 Before (org.junit.Before)9 RequestInfo (com.nike.riposte.server.http.RequestInfo)8 Tracer (com.nike.wingtips.Tracer)8 HttpTagAndSpanNamingAdapter (com.nike.wingtips.tags.HttpTagAndSpanNamingAdapter)7 ChannelFuture (io.netty.channel.ChannelFuture)7 ChannelHandler (io.netty.channel.ChannelHandler)7 ChannelHandlerContext (io.netty.channel.ChannelHandlerContext)7 HttpResponse (io.netty.handler.codec.http.HttpResponse)7 LastHttpContent (io.netty.handler.codec.http.LastHttpContent)7