Search in sources :

Example 21 with Span

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

the class ChannelPipelineFinalizerHandlerTest method doChannelInactive_does_what_it_can_when_the_HttpProcessingState_or_ProxyRouterProcessingState_is_null.

@DataProvider(value = { "true   |   false", "false  |   true", "true   |   true" }, splitBy = "\\|")
@Test
public void doChannelInactive_does_what_it_can_when_the_HttpProcessingState_or_ProxyRouterProcessingState_is_null(boolean httpStateIsNull, boolean proxyRouterStateIsNull) throws Exception {
    // given
    if (httpStateIsNull)
        doReturn(null).when(stateAttributeMock).get();
    if (proxyRouterStateIsNull)
        doReturn(null).when(proxyRouterProcessingStateAttributeMock).get();
    Span span = setupTracingForChannelInactive(false);
    // when
    PipelineContinuationBehavior result = handler.doChannelInactive(ctxMock);
    // then
    if (httpStateIsNull)
        Assertions.assertThat(span.isCompleted()).isFalse();
    else
        Assertions.assertThat(span.isCompleted()).isTrue();
    if (httpStateIsNull)
        verifyZeroInteractions(requestInfoMock);
    else
        verify(requestInfoMock).releaseAllResources();
    if (proxyRouterStateIsNull)
        verifyZeroInteractions(proxyRouterStateMock);
    else {
        verify(proxyRouterStateMock).cancelRequestStreaming(any(), any());
        verify(proxyRouterStateMock).cancelDownstreamRequest(any());
    }
    Assertions.assertThat(result).isEqualTo(PipelineContinuationBehavior.CONTINUE);
}
Also used : PipelineContinuationBehavior(com.nike.riposte.server.handler.base.PipelineContinuationBehavior) Span(com.nike.wingtips.Span) DataProvider(com.tngtech.java.junit.dataprovider.DataProvider) Test(org.junit.Test)

Example 22 with Span

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

the class ChannelPipelineFinalizerHandlerTest method doChannelInactive_does_what_it_can_when_the_RequestInfo_or_ResponseInfo_is_null.

@DataProvider(value = { "true   |   false", "false  |   true", "true   |   true" }, splitBy = "\\|")
@Test
public void doChannelInactive_does_what_it_can_when_the_RequestInfo_or_ResponseInfo_is_null(boolean requestInfoIsNull, boolean responseInfoIsNull) throws Exception {
    // given
    Span span = setupTracingForChannelInactive(false);
    if (requestInfoIsNull)
        state.setRequestInfo(null);
    if (responseInfoIsNull)
        state.setResponseInfo(null);
    // when
    PipelineContinuationBehavior result = handler.doChannelInactive(ctxMock);
    // then
    Assertions.assertThat(span.isCompleted()).isTrue();
    Assertions.assertThat(state.isTraceCompletedOrScheduled()).isTrue();
    if (requestInfoIsNull)
        verifyZeroInteractions(requestInfoMock);
    else
        verify(requestInfoMock).releaseAllResources();
    verify(proxyRouterStateMock).cancelRequestStreaming(any(), any());
    verify(proxyRouterStateMock).cancelDownstreamRequest(any());
    Assertions.assertThat(result).isEqualTo(PipelineContinuationBehavior.CONTINUE);
}
Also used : PipelineContinuationBehavior(com.nike.riposte.server.handler.base.PipelineContinuationBehavior) Span(com.nike.wingtips.Span) DataProvider(com.tngtech.java.junit.dataprovider.DataProvider) Test(org.junit.Test)

Example 23 with Span

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

the class DTraceEndHandlerTest method endDtrace_completes_the_trace_using_ChannelFutureListener_if_state_is_not_null_and_isResponseSendingLastChunkSent_returns_true.

@Test
public void endDtrace_completes_the_trace_using_ChannelFutureListener_if_state_is_not_null_and_isResponseSendingLastChunkSent_returns_true() throws Exception {
    // given
    assertThat(state.isTraceCompletedOrScheduled(), is(false));
    assertThat(state.isResponseSendingLastChunkSent(), is(true));
    assertThat(state.getDistributedTraceStack(), nullValue());
    Pair<Deque<Span>, Map<String, String>> expectedDtraceInfo = setupStateWithNewSpan("blahTrace");
    assertThat(state.getDistributedTraceStack(), notNullValue());
    assertThat(state.getDistributedTraceStack(), is(expectedDtraceInfo.getLeft()));
    assertThat(state.getDistributedTraceStack().size(), is(1));
    Span expectedSpan = expectedDtraceInfo.getLeft().peek();
    // when
    handlerSpy.endDtrace(ctxMock);
    // then
    // completeCurrentSpan() not immediately called, but scheduled
    verify(handlerSpy, never()).completeCurrentSpan();
    assertThat(state.isTraceCompletedOrScheduled(), is(true));
    // Extract the listener that was attached to the last chunk future.
    GenericFutureListener lastChunkListener = extractChannelFutureListenerAddedToLastChunkFuture();
    assertThat(lastChunkListener, notNullValue());
    assertThat(lastChunkListener, instanceOf(ChannelFutureListenerWithTracingAndMdc.class));
    assertThat(Whitebox.getInternalState(lastChunkListener, "distributedTraceStackForExecution"), is(expectedDtraceInfo.getLeft()));
    assertThat(Whitebox.getInternalState(lastChunkListener, "mdcContextMapForExecution"), is(expectedDtraceInfo.getRight()));
    Consumer<ChannelFuture> embeddedListenerConsumer = (Consumer<ChannelFuture>) Whitebox.getInternalState(lastChunkListener, "postCompleteOperation");
    // Execute the embedded listener so we can validate what it does. Note that we can't verify using mockito spy verify(),
    // because the method call goes through the internal handler, not the spy impl. But we can still verify by
    // setting up the Tracer state to what we expect, execute the embedded listener, and verify subsequent Tracer state.
    AsyncNettyHelper.linkTracingAndMdcToCurrentThread(expectedDtraceInfo);
    assertThat(Tracer.getInstance().getCurrentSpan(), is(expectedSpan));
    embeddedListenerConsumer.accept(null);
    assertThat(Tracer.getInstance().getCurrentSpan(), nullValue());
}
Also used : ChannelFuture(io.netty.channel.ChannelFuture) Consumer(java.util.function.Consumer) ChannelFutureListenerWithTracingAndMdc(com.nike.riposte.util.asynchelperwrapper.ChannelFutureListenerWithTracingAndMdc) Deque(java.util.Deque) Map(java.util.Map) Span(com.nike.wingtips.Span) GenericFutureListener(io.netty.util.concurrent.GenericFutureListener) Test(org.junit.Test)

Example 24 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.httpMethod, requestBuilderWrapper.url, circuitBreakerManualTask, distributedTraceStackForCall, mdcContextForCall);
        // Add distributed trace headers to the downstream call if we have a span.
        Span spanForCall = asyncCompletionHandler.getSpanForCall();
        if (spanForCall != null) {
            requestBuilderWrapper.requestBuilder.setHeader(TraceHeaders.TRACE_SAMPLED, String.valueOf(spanForCall.isSampleable()));
            requestBuilderWrapper.requestBuilder.setHeader(TraceHeaders.TRACE_ID, spanForCall.getTraceId());
            requestBuilderWrapper.requestBuilder.setHeader(TraceHeaders.SPAN_ID, spanForCall.getSpanId());
            requestBuilderWrapper.requestBuilder.setHeader(TraceHeaders.PARENT_SPAN_ID, spanForCall.getParentSpanId());
            requestBuilderWrapper.requestBuilder.setHeader(TraceHeaders.SPAN_NAME, spanForCall.getSpanName());
        }
        // 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 25 with Span

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

the class AsyncCompletionHandlerWithTracingAndMdcSupportTest method constructor_sets_values_with_subspan_when_subtracing_is_on.

@DataProvider(value = { "NULL", "EMPTY", "HAS_EXISTING_SPAN" }, splitBy = "\\|")
@Test
public void constructor_sets_values_with_subspan_when_subtracing_is_on(ExistingSpanStackState existingSpanStackState) {
    // given
    CompletableFuture cfResponse = mock(CompletableFuture.class);
    AsyncResponseHandler responseHandlerFunc = mock(AsyncResponseHandler.class);
    String method = UUID.randomUUID().toString();
    String url = UUID.randomUUID().toString();
    Optional<CircuitBreaker<Response>> circuitBreaker = Optional.of(mock(CircuitBreaker.class));
    Span initialSpan = null;
    switch(existingSpanStackState) {
        case NULL:
        case // intentional fall-through
        EMPTY:
            resetTracingAndMdc();
            break;
        case HAS_EXISTING_SPAN:
            initialSpan = Tracer.getInstance().startRequestWithRootSpan("overallReqSpan");
            break;
        default:
            throw new IllegalArgumentException("Unhandled state: " + existingSpanStackState.name());
    }
    Deque<Span> spanStack = (existingSpanStackState == EMPTY) ? new LinkedList<>() : Tracer.getInstance().getCurrentSpanStackCopy();
    Map<String, String> mdcInfo = (existingSpanStackState == EMPTY) ? new HashMap<>() : MDC.getCopyOfContextMap();
    resetTracingAndMdc();
    Deque<Span> spanStackBeforeCall = Tracer.getInstance().getCurrentSpanStackCopy();
    Map<String, String> mdcInfoBeforeCall = MDC.getCopyOfContextMap();
    // when
    AsyncCompletionHandlerWithTracingAndMdcSupport instance = new AsyncCompletionHandlerWithTracingAndMdcSupport(cfResponse, responseHandlerFunc, true, method, url, circuitBreaker, spanStack, mdcInfo);
    // then
    assertThat(instance.completableFutureResponse).isSameAs(cfResponse);
    assertThat(instance.responseHandlerFunction).isSameAs(responseHandlerFunc);
    assertThat(instance.performSubSpanAroundDownstreamCalls).isEqualTo(true);
    assertThat(instance.circuitBreakerManualTask).isSameAs(circuitBreaker);
    int initialSpanStackSize = (spanStack == null) ? 0 : spanStack.size();
    assertThat(instance.distributedTraceStackToUse).hasSize(initialSpanStackSize + 1);
    Span subspan = (Span) instance.distributedTraceStackToUse.peek();
    assertThat(instance.mdcContextToUse.get(Tracer.TRACE_ID_MDC_KEY)).isEqualTo(subspan.getTraceId());
    if (existingSpanStackState == ExistingSpanStackState.NULL || existingSpanStackState == EMPTY) {
        assertThat(instance.distributedTraceStackToUse).hasSize(1);
    } else {
        assertThat(instance.distributedTraceStackToUse.peekLast()).isEqualTo(initialSpan);
        assertThat(subspan).isNotEqualTo(initialSpan);
        assertThat(subspan.getTraceId()).isEqualTo(initialSpan.getTraceId());
        assertThat(subspan.getParentSpanId()).isEqualTo(initialSpan.getSpanId());
        assertThat(subspan.getSpanName()).isEqualTo(instance.getSubspanSpanName(method, url));
    }
    assertThat(Tracer.getInstance().getCurrentSpanStackCopy()).isEqualTo(spanStackBeforeCall);
    assertThat(MDC.getCopyOfContextMap()).isEqualTo(mdcInfoBeforeCall);
}
Also used : CircuitBreaker(com.nike.fastbreak.CircuitBreaker) Span(com.nike.wingtips.Span) CompletableFuture(java.util.concurrent.CompletableFuture) DataProvider(com.tngtech.java.junit.dataprovider.DataProvider) Test(org.junit.Test)

Aggregations

Span (com.nike.wingtips.Span)46 Test (org.junit.Test)38 DataProvider (com.tngtech.java.junit.dataprovider.DataProvider)21 Map (java.util.Map)14 Deque (java.util.Deque)13 Assertions.catchThrowable (org.assertj.core.api.Assertions.catchThrowable)9 CompletableFuture (java.util.concurrent.CompletableFuture)7 HashMap (java.util.HashMap)6 HttpProcessingState (com.nike.riposte.server.http.HttpProcessingState)5 Tracer (com.nike.wingtips.Tracer)4 ChannelFuture (io.netty.channel.ChannelFuture)4 LinkedList (java.util.LinkedList)4 CircuitBreaker (com.nike.fastbreak.CircuitBreaker)3 PipelineContinuationBehavior (com.nike.riposte.server.handler.base.PipelineContinuationBehavior)3 RequestInfo (com.nike.riposte.server.http.RequestInfo)3 ChannelHandlerContext (io.netty.channel.ChannelHandlerContext)3 Matchers.anyString (org.mockito.Matchers.anyString)3 WrapperException (com.nike.backstopper.exception.WrapperException)2 Pair (com.nike.internal.util.Pair)2 DownstreamIdleChannelTimeoutHandler (com.nike.riposte.client.asynchttp.netty.downstreampipeline.DownstreamIdleChannelTimeoutHandler)2