use of com.nike.wingtips.Span in project riposte by Nike-Inc.
the class DTraceStartHandler method doChannelRead.
@Override
public PipelineContinuationBehavior doChannelRead(ChannelHandlerContext ctx, Object msg) {
// We only do the processing for HttpRequest which is the first message in a request chain.
if (shouldHandleDoChannelReadMessage(msg)) {
try {
startTrace((HttpRequest) msg, ctx);
} catch (Throwable t) {
logger.error("An unexpected error occurred while starting the distributed tracing overall request span. This " + "exception will be swallowed to avoid breaking the Netty pipeline, but it should be " + "investigated as it shouldn't ever happen.", t);
}
}
if (msg instanceof LastHttpContent) {
HttpProcessingState httpProcessingState = ChannelAttributes.getHttpProcessingStateForChannel(ctx).get();
// Add the "we received the last bytes of the request on the wire" annotation to the span if possible
// and desired.
Span requestSpan = handlerUtils.getOverallRequestSpan(httpProcessingState);
if (requestSpan != null && spanNamingAndTaggingStrategy.shouldAddWireReceiveFinishAnnotation()) {
requestSpan.addTimestampedAnnotationForCurrentTime(spanNamingAndTaggingStrategy.wireReceiveFinishAnnotationName());
}
}
return PipelineContinuationBehavior.CONTINUE;
}
use of com.nike.wingtips.Span in project riposte by Nike-Inc.
the class DTraceStartHandler method startTrace.
protected void startTrace(HttpRequest nettyRequest, ChannelHandlerContext ctx) {
Tracer tracer = Tracer.getInstance();
// Start the distributed trace.
RequestWithHeaders requestWrapper = new RequestWithHeadersNettyAdapter(nettyRequest);
final Span parentSpan = HttpRequestTracingUtils.fromRequestWithHeaders(requestWrapper, userIdHeaderKeys);
HttpProcessingState httpProcessingState = ChannelAttributes.getHttpProcessingStateForChannel(ctx).get();
// Create the new trace or child span, depending on what info came through via the Netty HttpRequest.
// We'll use the fallback span name to start with, because it's possible to throw an exception when
// creating the Riposte RequestInfo from the HttpRequest (which can happen when we call
// handlerUtils.createRequestInfoFromNettyHttpRequestAndHandleStateSetupIfNecessary(...) for certain
// bad requests), and we want the log message for *that* to include trace ID.
Span newSpan;
if (parentSpan != null) {
newSpan = tracer.startRequestWithChildSpan(parentSpan, handlerUtils.determineFallbackOverallRequestSpanName(nettyRequest));
logger.debug("Found Parent Span {}", parentSpan);
} else {
newSpan = tracer.startRequestWithRootSpan(handlerUtils.determineFallbackOverallRequestSpanName(nettyRequest), HttpRequestTracingUtils.getUserIdFromRequestWithHeaders(requestWrapper, userIdHeaderKeys));
logger.debug("Parent Span not found, starting a new trace with root span {}", newSpan);
}
// Add the "we received the first bytes of the request on the wire" annotation to the span if desired.
if (spanNamingAndTaggingStrategy.shouldAddWireReceiveStartAnnotation()) {
newSpan.addTimestampedAnnotationForCurrentTime(spanNamingAndTaggingStrategy.wireReceiveStartAnnotationName());
}
// Get the RequestInfo (generating it from the given Netty HttpRequest if necessary), so that
// getSpanName() can use it to come up with a better initial span name.
RequestInfo<?> riposteRequestInfo = (httpProcessingState == null) ? null : handlerUtils.createRequestInfoFromNettyHttpRequestAndHandleStateSetupIfNecessary(nettyRequest, httpProcessingState);
if (riposteRequestInfo != null) {
// Change the span name based on what the tag strategy wants now that we have a Riposte RequestInfo.
spanNamingAndTaggingStrategy.changeSpanName(newSpan, handlerUtils.determineOverallRequestSpanName(nettyRequest, riposteRequestInfo, spanNamingAndTaggingStrategy));
// Add request tagging.
spanNamingAndTaggingStrategy.handleRequestTagging(newSpan, riposteRequestInfo);
}
}
use of com.nike.wingtips.Span in project riposte by Nike-Inc.
the class AsyncHttpClientHelperTest method executeAsyncHttpRequest_with_ctx_extracts_mdc_and_tracing_info_from_ctx_and_delegates_to_kitchen_sink_execute_method.
@Test
public void executeAsyncHttpRequest_with_ctx_extracts_mdc_and_tracing_info_from_ctx_and_delegates_to_kitchen_sink_execute_method() {
// given
RequestBuilderWrapper rbwMock = mock(RequestBuilderWrapper.class);
AsyncResponseHandler responseHandlerMock = mock(AsyncResponseHandler.class);
CompletableFuture cfMock = mock(CompletableFuture.class);
doReturn(cfMock).when(helperSpy).executeAsyncHttpRequest(any(RequestBuilderWrapper.class), any(AsyncResponseHandler.class), any(Deque.class), any(Map.class));
Map<String, String> mdcMock = mock(Map.class);
Deque<Span> spanStackMock = mock(Deque.class);
state.setLoggerMdcContextMap(mdcMock);
state.setDistributedTraceStack(spanStackMock);
// when
CompletableFuture result = helperSpy.executeAsyncHttpRequest(rbwMock, responseHandlerMock, ctxMock);
// then
verify(helperSpy).executeAsyncHttpRequest(rbwMock, responseHandlerMock, spanStackMock, mdcMock);
assertThat(result).isSameAs(cfMock);
verify(rbwMock).setCtx(ctxMock);
}
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(initialSpanNameFromStrategy.get());
if (initialSpan != null) {
assertThat(subspan.getTraceId()).isEqualTo(initialSpan.getTraceId());
assertThat(subspan.getParentSpanId()).isEqualTo(initialSpan.getSpanId());
}
assertThat(achwtams.mdcContextToUse.get(SpanFieldForLoggerMdc.TRACE_ID.mdcKey)).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();
verifyNoMoreInteractions(reqMock);
} else {
assertThat(spanForDownstreamCall).isNotNull();
verify(reqMock).setHeader(TraceHeaders.TRACE_SAMPLED, convertSampleableBooleanToExpectedB3Value(spanForDownstreamCall.isSampleable()));
verify(reqMock).setHeader(TraceHeaders.TRACE_ID, spanForDownstreamCall.getTraceId());
verify(reqMock).setHeader(TraceHeaders.SPAN_ID, spanForDownstreamCall.getSpanId());
if (spanForDownstreamCall.getParentSpanId() == null) {
verify(reqMock, never()).setHeader(eq(TraceHeaders.PARENT_SPAN_ID), anyString());
} else {
verify(reqMock).setHeader(TraceHeaders.PARENT_SPAN_ID, spanForDownstreamCall.getParentSpanId());
}
verify(reqMock, never()).setHeader(eq(TraceHeaders.SPAN_NAME), anyString());
}
// Verify that any subspan had request tagging performed.
if (performSubspan) {
strategyRequestTaggingArgs.get().verifyArgs(spanForDownstreamCall, rbw, wingtipsTagAndNamingAdapterMock);
}
}
use of com.nike.wingtips.Span in project riposte by Nike-Inc.
the class AsyncHttpClientHelperTest method basic_executeAsyncHttpRequest_extracts_mdc_and_tracing_info_from_current_thread_and_delegates_to_kitchen_sink_execute_method.
@Test
public void basic_executeAsyncHttpRequest_extracts_mdc_and_tracing_info_from_current_thread_and_delegates_to_kitchen_sink_execute_method() {
// given
RequestBuilderWrapper rbw = mock(RequestBuilderWrapper.class);
AsyncResponseHandler responseHandler = mock(AsyncResponseHandler.class);
CompletableFuture cfMock = mock(CompletableFuture.class);
doReturn(cfMock).when(helperSpy).executeAsyncHttpRequest(any(RequestBuilderWrapper.class), any(AsyncResponseHandler.class), any(Deque.class), any(Map.class));
Tracer.getInstance().startRequestWithRootSpan("foo");
Deque<Span> expectedSpanStack = Tracer.getInstance().getCurrentSpanStackCopy();
Map<String, String> expectedMdc = MDC.getCopyOfContextMap();
// when
CompletableFuture result = helperSpy.executeAsyncHttpRequest(rbw, responseHandler);
// then
verify(helperSpy).executeAsyncHttpRequest(rbw, responseHandler, expectedSpanStack, expectedMdc);
assertThat(result).isSameAs(cfMock);
}
Aggregations