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());
}
}
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());
}
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);
}
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);
}
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());
}
Aggregations