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