Search in sources :

Example 26 with Span

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

the class AsyncHttpClientHelperTest method executeAsyncHttpRequest_sets_up_and_executes_call_as_expected.

@DataProvider(value = { "true   |   true", "true   |   false", "false  |   true", "false  |   false" }, splitBy = "\\|")
@Test
public void executeAsyncHttpRequest_sets_up_and_executes_call_as_expected(boolean performSubspan, boolean currentTracingInfoNull) {
    // given
    Whitebox.setInternalState(helperSpy, "performSubSpanAroundDownstreamCalls", performSubspan);
    CircuitBreaker<Response> circuitBreakerMock = mock(CircuitBreaker.class);
    doReturn(Optional.of(circuitBreakerMock)).when(helperSpy).getCircuitBreaker(any(RequestBuilderWrapper.class));
    ManualModeTask<Response> cbManualTaskMock = mock(ManualModeTask.class);
    doReturn(cbManualTaskMock).when(circuitBreakerMock).newManualModeTask();
    String url = "http://localhost/some/path";
    String method = "GET";
    AsyncHttpClient.BoundRequestBuilder reqMock = mock(AsyncHttpClient.BoundRequestBuilder.class);
    RequestBuilderWrapper rbw = new RequestBuilderWrapper(url, method, reqMock, Optional.empty(), false);
    AsyncResponseHandler responseHandlerMock = mock(AsyncResponseHandler.class);
    Span initialSpan = (currentTracingInfoNull) ? null : Tracer.getInstance().startRequestWithRootSpan("foo");
    Deque<Span> initialSpanStack = (currentTracingInfoNull) ? null : Tracer.getInstance().getCurrentSpanStackCopy();
    Map<String, String> initialMdc = (currentTracingInfoNull) ? null : MDC.getCopyOfContextMap();
    resetTracingAndMdc();
    // when
    CompletableFuture resultFuture = helperSpy.executeAsyncHttpRequest(rbw, responseHandlerMock, initialSpanStack, initialMdc);
    // then
    // Verify that the circuit breaker came from the getCircuitBreaker helper method and that its
    // throwExceptionIfCircuitBreakerIsOpen() method was called.
    verify(helperSpy).getCircuitBreaker(rbw);
    verify(cbManualTaskMock).throwExceptionIfCircuitBreakerIsOpen();
    // Verify that the inner request's execute method was called with a
    // AsyncCompletionHandlerWithTracingAndMdcSupport for the handler.
    ArgumentCaptor<AsyncHandler> executedHandlerCaptor = ArgumentCaptor.forClass(AsyncHandler.class);
    verify(reqMock).execute(executedHandlerCaptor.capture());
    AsyncHandler executedHandler = executedHandlerCaptor.getValue();
    assertThat(executedHandler).isInstanceOf(AsyncCompletionHandlerWithTracingAndMdcSupport.class);
    // Verify that the AsyncCompletionHandlerWithTracingAndMdcSupport was created with the expected args
    AsyncCompletionHandlerWithTracingAndMdcSupport achwtams = (AsyncCompletionHandlerWithTracingAndMdcSupport) executedHandler;
    assertThat(achwtams.completableFutureResponse).isSameAs(resultFuture);
    assertThat(achwtams.responseHandlerFunction).isSameAs(responseHandlerMock);
    assertThat(achwtams.performSubSpanAroundDownstreamCalls).isEqualTo(performSubspan);
    assertThat(achwtams.circuitBreakerManualTask).isEqualTo(Optional.of(cbManualTaskMock));
    if (performSubspan) {
        int initialSpanStackSize = (initialSpanStack == null) ? 0 : initialSpanStack.size();
        assertThat(achwtams.distributedTraceStackToUse).hasSize(initialSpanStackSize + 1);
        Span subspan = (Span) achwtams.distributedTraceStackToUse.peek();
        assertThat(subspan.getSpanName()).isEqualTo(handlerWithTracingAndMdcDummyExample.getSubspanSpanName(method, url));
        if (initialSpan != null) {
            assertThat(subspan.getTraceId()).isEqualTo(initialSpan.getTraceId());
            assertThat(subspan.getParentSpanId()).isEqualTo(initialSpan.getSpanId());
        }
        assertThat(achwtams.mdcContextToUse.get(Tracer.TRACE_ID_MDC_KEY)).isEqualTo(subspan.getTraceId());
    } else {
        assertThat(achwtams.distributedTraceStackToUse).isSameAs(initialSpanStack);
        assertThat(achwtams.mdcContextToUse).isSameAs(initialMdc);
    }
    // Verify that the trace headers were added (or not depending on state).
    Span spanForDownstreamCall = achwtams.getSpanForCall();
    if (initialSpan == null && !performSubspan) {
        assertThat(spanForDownstreamCall).isNull();
        verifyZeroInteractions(reqMock);
    } else {
        assertThat(spanForDownstreamCall).isNotNull();
        verify(reqMock).setHeader(TraceHeaders.TRACE_SAMPLED, String.valueOf(spanForDownstreamCall.isSampleable()));
        verify(reqMock).setHeader(TraceHeaders.TRACE_ID, spanForDownstreamCall.getTraceId());
        verify(reqMock).setHeader(TraceHeaders.SPAN_ID, spanForDownstreamCall.getSpanId());
        verify(reqMock).setHeader(TraceHeaders.PARENT_SPAN_ID, spanForDownstreamCall.getParentSpanId());
        verify(reqMock).setHeader(TraceHeaders.SPAN_NAME, spanForDownstreamCall.getSpanName());
    }
}
Also used : AsyncHandler(com.ning.http.client.AsyncHandler) Matchers.anyString(org.mockito.Matchers.anyString) Span(com.nike.wingtips.Span) Response(com.ning.http.client.Response) CompletableFuture(java.util.concurrent.CompletableFuture) AsyncHttpClient(com.ning.http.client.AsyncHttpClient) DataProvider(com.tngtech.java.junit.dataprovider.DataProvider) Test(org.junit.Test)

Example 27 with Span

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

the class VerifyAsyncHttpClientHelperComponentTest method verify_basic_functionality.

@Test
public void verify_basic_functionality() throws Exception {
    // given
    RequestBuilderWrapper rbw = asyncClient.getRequestBuilder("http://localhost:" + serverPort + TestEndpoint.MATCHING_PATH, HttpMethod.GET);
    rbw.requestBuilder.setHeader(TestEndpoint.EXPECTED_HEADER_KEY, TestEndpoint.EXPECTED_HEADER_VAL);
    rbw.requestBuilder.setBody(TestEndpoint.EXPECTED_REQUEST_PAYLOAD);
    Span origSpan = Tracer.getInstance().startRequestWithRootSpan("overallReqSpan");
    Deque<Span> distributedTraceStackForCall = Tracer.getInstance().getCurrentSpanStackCopy();
    Map<String, String> mdcContextForCall = MDC.getCopyOfContextMap();
    resetTracingAndMdc();
    // when
    Response result = asyncClient.executeAsyncHttpRequest(rbw, response -> response, distributedTraceStackForCall, mdcContextForCall).join();
    // then
    assertThat(result.getStatusCode()).isEqualTo(200);
    assertThat(result.getResponseBody()).isEqualTo(TestEndpoint.RESPONSE_PAYLOAD);
    assertThat(result.getHeader(TraceHeaders.TRACE_ID)).isEqualTo(origSpan.getTraceId());
    // The async client should have surrounded the request in a subspan,
    // so the parent ID sent to the downstream service should be the original span's span ID.
    assertThat(result.getHeader(TraceHeaders.PARENT_SPAN_ID)).isEqualTo(origSpan.getSpanId());
}
Also used : Response(com.ning.http.client.Response) Span(com.nike.wingtips.Span) RequestInfo(com.nike.riposte.server.http.RequestInfo) BeforeClass(org.junit.BeforeClass) Assertions.assertThat(org.assertj.core.api.Assertions.assertThat) ResponseInfo(com.nike.riposte.server.http.ResponseInfo) TraceHeaders(com.nike.wingtips.TraceHeaders) Tracer(com.nike.wingtips.Tracer) CompletableFuture(java.util.concurrent.CompletableFuture) ServerConfig(com.nike.riposte.server.config.ServerConfig) Deque(java.util.Deque) ServerSocket(java.net.ServerSocket) ChannelHandlerContext(io.netty.channel.ChannelHandlerContext) Collections.singleton(java.util.Collections.singleton) ApiError(com.nike.backstopper.apierror.ApiError) After(org.junit.After) Map(java.util.Map) Server(com.nike.riposte.server.Server) AsyncHttpClientHelper(com.nike.riposte.client.asynchttp.ning.AsyncHttpClientHelper) Response(com.ning.http.client.Response) Before(org.junit.Before) AfterClass(org.junit.AfterClass) ApiException(com.nike.backstopper.exception.ApiException) Executor(java.util.concurrent.Executor) Collection(java.util.Collection) HttpMethod(io.netty.handler.codec.http.HttpMethod) Test(org.junit.Test) IOException(java.io.IOException) StandardEndpoint(com.nike.riposte.server.http.StandardEndpoint) UUID(java.util.UUID) ApiErrorBase(com.nike.backstopper.apierror.ApiErrorBase) Endpoint(com.nike.riposte.server.http.Endpoint) Matcher(com.nike.riposte.util.Matcher) DefaultHttpHeaders(io.netty.handler.codec.http.DefaultHttpHeaders) MDC(org.slf4j.MDC) RequestBuilderWrapper(com.nike.riposte.client.asynchttp.ning.RequestBuilderWrapper) RequestBuilderWrapper(com.nike.riposte.client.asynchttp.ning.RequestBuilderWrapper) Span(com.nike.wingtips.Span) Test(org.junit.Test)

Example 28 with Span

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

the class AsyncNettyHelperTest method linkTracingAndMdcToCurrentThread_separate_args_works_as_expected.

@DataProvider(value = { "true   |   true", "false  |   true", "true   |   false", "false  |   false" }, splitBy = "\\|")
@Test
public void linkTracingAndMdcToCurrentThread_separate_args_works_as_expected(boolean useNullSpanStack, boolean useNullMdcInfo) {
    // given
    Pair<Deque<Span>, Map<String, String>> info = setupStateWithTracingAndMdcInfo();
    info.getRight().put("fooMdcKey", UUID.randomUUID().toString());
    Deque<Span> spanStackForLinking = (useNullSpanStack) ? null : info.getLeft();
    Map<String, String> mdcInfoForLinking = (useNullMdcInfo) ? null : info.getRight();
    resetTracingAndMdc();
    Tracer.getInstance().startRequestWithRootSpan("foo-" + UUID.randomUUID().toString());
    Pair<Deque<Span>, Map<String, String>> expectedPreCallInfo = Pair.of(Tracer.getInstance().getCurrentSpanStackCopy(), MDC.getCopyOfContextMap());
    Map<String, String> expectedMdcInfo;
    // The expected MDC info will vary depending on combinations.
    if (useNullMdcInfo) {
        // MDC may still be populated after the call if the span stack is not empty
        if (useNullSpanStack)
            expectedMdcInfo = Collections.emptyMap();
        else {
            // MDC will have been populated with tracing info.
            expectedMdcInfo = new HashMap<>();
            Span expectedSpan = spanStackForLinking.peek();
            expectedMdcInfo.put(Tracer.TRACE_ID_MDC_KEY, expectedSpan.getTraceId());
            expectedMdcInfo.put(Tracer.SPAN_JSON_MDC_KEY, expectedSpan.toJSON());
        }
    } else {
        // Not null MDC. Start with the MDC info for linking.
        expectedMdcInfo = new HashMap<>(mdcInfoForLinking);
        if (useNullSpanStack) {
            // In the case of a null span stack, the trace info would be removed from the MDC.
            expectedMdcInfo.remove(Tracer.TRACE_ID_MDC_KEY);
            expectedMdcInfo.remove(Tracer.SPAN_JSON_MDC_KEY);
        }
    }
    // when
    Pair<Deque<Span>, Map<String, String>> preCallInfo = AsyncNettyHelper.linkTracingAndMdcToCurrentThread(spanStackForLinking, mdcInfoForLinking);
    Pair<Deque<Span>, Map<String, String>> postCallInfo = Pair.of(Tracer.getInstance().getCurrentSpanStackCopy(), MDC.getCopyOfContextMap());
    // then
    assertThat(preCallInfo).isEqualTo(expectedPreCallInfo);
    assertThat(postCallInfo.getLeft()).isEqualTo(spanStackForLinking);
    assertThat(postCallInfo.getRight()).isEqualTo(expectedMdcInfo);
}
Also used : Deque(java.util.Deque) Map(java.util.Map) HashMap(java.util.HashMap) Span(com.nike.wingtips.Span) DataProvider(com.tngtech.java.junit.dataprovider.DataProvider) Test(org.junit.Test)

Example 29 with Span

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

the class AsyncNettyHelperTest method executeAsyncCall_shouldReturnCompletableFutureUsingCircuitBreaker.

@Test
public void executeAsyncCall_shouldReturnCompletableFutureUsingCircuitBreaker() throws Exception {
    // given
    String expectedResult = UUID.randomUUID().toString();
    ctxMock = TestUtil.mockChannelHandlerContextWithTraceInfo().mockContext;
    CircuitBreaker<String> circuitBreaker = spy(new CircuitBreakerImpl<>());
    Span parentSpan = Tracer.getInstance().getCurrentSpan();
    AtomicReference<Span> runningSpan = new AtomicReference<>();
    // when
    CompletableFuture<String> circuitBreakerCompletableFuture = AsyncNettyHelper.supplyAsync(() -> {
        runningSpan.set(Tracer.getInstance().getCurrentSpan());
        return expectedResult;
    }, circuitBreaker, executor, ctxMock);
    // then
    verify(circuitBreaker).executeAsyncCall(anyObject());
    assertThat(circuitBreakerCompletableFuture.isCompletedExceptionally()).isFalse();
    assertThat(circuitBreakerCompletableFuture.get()).isEqualTo(expectedResult);
    // verify new span is not created, but existing span does successfully hop threads
    assertThat(runningSpan.get()).isEqualTo(parentSpan);
}
Also used : AtomicReference(java.util.concurrent.atomic.AtomicReference) Span(com.nike.wingtips.Span) Test(org.junit.Test)

Example 30 with Span

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

the class AsyncNettyHelperTest method executeAsyncCall_shouldReturnCompletableFutureUsingCircuitBreakerWithSpanName.

@Test
public void executeAsyncCall_shouldReturnCompletableFutureUsingCircuitBreakerWithSpanName() throws Exception {
    // given
    String expectedResult = UUID.randomUUID().toString();
    String expectedSpanName = "circuitBreakerWithSpan";
    ctxMock = TestUtil.mockChannelHandlerContextWithTraceInfo().mockContext;
    Span parentSpan = Tracer.getInstance().getCurrentSpan();
    CircuitBreaker<String> circuitBreaker = spy(new CircuitBreakerImpl<>());
    AtomicReference<Span> runningSpan = new AtomicReference<>();
    // when
    CompletableFuture<String> circuitBreakerFuture = AsyncNettyHelper.supplyAsync(expectedSpanName, () -> {
        runningSpan.set(Tracer.getInstance().getCurrentSpan());
        return expectedResult;
    }, circuitBreaker, executor, ctxMock);
    // then
    assertThat(circuitBreakerFuture.isCompletedExceptionally()).isFalse();
    assertThat(circuitBreakerFuture.get()).isEqualTo(expectedResult);
    verify(circuitBreaker).executeAsyncCall(anyObject());
    // verify span is as expected
    assertThat(runningSpan.get().getParentSpanId()).isEqualTo(parentSpan.getSpanId());
    assertThat(runningSpan.get().getSpanName()).isEqualTo(expectedSpanName);
    assertThat(runningSpan.get().getTraceId()).isEqualTo(parentSpan.getTraceId());
}
Also used : AtomicReference(java.util.concurrent.atomic.AtomicReference) Span(com.nike.wingtips.Span) 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