下面列出了org.apache.http.client.methods.HttpExecutionAware#com.nike.wingtips.Span 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
@DataProvider(value = {
"true",
"false"
})
@Test
public void kitchen_sink_constructor_sets_fields_as_expected(boolean useStaticFactory) {
// given
Deque<Span> spanStackMock = mock(Deque.class);
Map<String, String> mdcInfoMock = mock(Map.class);
// when
RunnableWithTracing instance = (useStaticFactory)
? withTracing(runnableMock, spanStackMock, mdcInfoMock)
: new RunnableWithTracing(runnableMock, spanStackMock, mdcInfoMock);
// then
assertThat(instance.origRunnable).isSameAs(runnableMock);
assertThat(instance.spanStackForExecution).isEqualTo(spanStackMock);
assertThat(instance.mdcContextMapForExecution).isEqualTo(mdcInfoMock);
}
@Test
public void fromHttpServletRequest_generates_new_spanId_if_missing_from_headers() {
// given: a request with a trace ID but no span ID in the headers
String traceId = UUID.randomUUID().toString();
given(request.getHeader(TraceHeaders.TRACE_ID)).willReturn(traceId);
// when: we use it to create span objects
Span firstSpan = HttpSpanFactory.fromHttpServletRequest(request, USER_ID_HEADER_KEYS);
Span secondSpan = HttpSpanFactory.fromHttpServletRequest(request, USER_ID_HEADER_KEYS);
// then: ensure each call generates a span with the same trace ID but new span ID
assertThat(firstSpan.getTraceId()).isEqualTo(traceId);
assertThat(secondSpan.getTraceId()).isEqualTo(traceId);
assertThat(firstSpan.getSpanId()).isNotEmpty();
assertThat(secondSpan.getSpanId()).isNotEmpty();
assertThat(firstSpan.getSpanId()).isNotEqualTo(secondSpan.getSpanId());
}
@Test
public void linkTracingAndMdcToCurrentThread_pair_works_as_expected_with_non_null_pair_and_null_innards() {
// given
Pair<Deque<Span>, Map<String, String>> infoForLinking = Pair.of(null, null);
resetTracingAndMdc();
Tracer.getInstance().startRequestWithRootSpan("foo-" + UUID.randomUUID().toString());
Pair<Deque<Span>, Map<String, String>> expectedPreCallInfo = Pair.of(
Tracer.getInstance().getCurrentSpanStackCopy(),
MDC.getCopyOfContextMap()
);
// when
Pair<Deque<Span>, Map<String, String>> preCallInfo =
AsyncNettyHelper.linkTracingAndMdcToCurrentThread(infoForLinking);
Pair<Deque<Span>, Map<String, String>> postCallInfo = Pair.of(
Tracer.getInstance().getCurrentSpanStackCopy(),
MDC.getCopyOfContextMap()
);
// then
assertThat(preCallInfo).isEqualTo(expectedPreCallInfo);
assertThat(postCallInfo).isEqualTo(Pair.of(null, Collections.emptyMap()));
}
@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);
}
@SuppressWarnings("ConstantConditions")
public ExceptionHandlingHandler(
@NotNull RiposteErrorHandler riposteErrorHandler,
@NotNull RiposteUnhandledErrorHandler riposteUnhandledErrorHandler,
@NotNull DistributedTracingConfig<Span> distributedTracingConfig
) {
if (riposteErrorHandler == null) {
throw new IllegalArgumentException("riposteErrorHandler cannot be null");
}
if (riposteUnhandledErrorHandler == null) {
throw new IllegalArgumentException("riposteUnhandledErrorHandler cannot be null");
}
if (distributedTracingConfig == null) {
throw new IllegalArgumentException("distributedTracingConfig cannot be null");
}
this.riposteErrorHandler = riposteErrorHandler;
this.riposteUnhandledErrorHandler = riposteUnhandledErrorHandler;
this.spanNamingAndTaggingStrategy = distributedTracingConfig.getServerSpanNamingAndTaggingStrategy();
}
@UseDataProvider("idSanitizationScenarios")
@Test
public void convertWingtipsSpanToZipkinSpan_sanitizes_spanId_as_expected_when_sanitization_is_enabled(
IdSanitizationScenario scenario
) {
// given
impl = new WingtipsToZipkinSpanConverterDefaultImpl(true);
final Endpoint zipkinEndpoint = Endpoint.newBuilder().serviceName(UUID.randomUUID().toString()).build();
final Span wingtipsSpan = Span.newBuilder("foo", SpanPurpose.CLIENT)
.withSpanId(scenario.originalId)
.withSpanStartTimeEpochMicros(Math.abs(random.nextLong()))
.withDurationNanos(Math.abs(random.nextLong()))
.build();
// when
zipkin2.Span zipkinSpan = impl.convertWingtipsSpanToZipkinSpan(wingtipsSpan, zipkinEndpoint);
// then
assertThat(zipkinSpan.id()).isEqualTo(scenario.expectedSanitizedResultForSpanIdOrParentSpanId);
assertThat(zipkinSpan.tags().get("invalid.span_id")).isEqualTo(scenario.originalId);
assertThat(wingtipsSpan.getTags().get("sanitized_span_id")).isEqualTo(scenario.expectedSanitizedResultForSpanIdOrParentSpanId);
}
@SuppressWarnings("ConstantConditions")
public NonblockingEndpointExecutionHandler(
@NotNull Executor longRunningTaskExecutor,
long defaultCompletableFutureTimeoutMillis,
@NotNull DistributedTracingConfig<Span> distributedTracingConfig
) {
if (longRunningTaskExecutor == null) {
throw new IllegalArgumentException("longRunningTaskExecutor cannot be null");
}
if (distributedTracingConfig == null) {
throw new IllegalArgumentException("distributedTracingConfig cannot be null");
}
this.longRunningTaskExecutor = longRunningTaskExecutor;
this.defaultCompletableFutureTimeoutMillis = defaultCompletableFutureTimeoutMillis;
this.spanTaggingStrategy = distributedTracingConfig.getServerSpanNamingAndTaggingStrategy();
}
@Test
public void constructors_throw_exception_if_passed_null_function() {
// given
Deque<Span> spanStackMock = mock(Deque.class);
Map<String, String> mdcInfoMock = mock(Map.class);
// expect
assertThat(catchThrowable(() -> new FunctionWithTracingAndMdcSupport(null, ctxMock)))
.isInstanceOf(IllegalArgumentException.class);
// and expect
assertThat(catchThrowable(() -> new FunctionWithTracingAndMdcSupport(null, Pair.of(spanStackMock, mdcInfoMock))))
.isInstanceOf(IllegalArgumentException.class);
// and expect
assertThat(catchThrowable(() -> new FunctionWithTracingAndMdcSupport(null, spanStackMock, mdcInfoMock)))
.isInstanceOf(IllegalArgumentException.class);
}
@DataProvider(value = {
"true",
"false"
})
@Test
public void consumerWithTracing_separate_args_works_as_expected(boolean useStaticMethod) {
// given
Pair<Deque<Span>, Map<String, String>> setupInfo = generateTracingInfo();
// when
Consumer result = (useStaticMethod)
? consumerWithTracing(consumerMock, setupInfo.getLeft(), setupInfo.getRight())
: DEFAULT_IMPL.consumerWithTracing(consumerMock,
setupInfo.getLeft(), setupInfo.getRight());
// then
verifyConsumerWithTracing(result, consumerMock, setupInfo.getLeft(), setupInfo.getRight());
}
@DataProvider(value = {
"true",
"false"
})
@Test
public void functionWithTracing_separate_args_works_as_expected(boolean useStaticMethod) {
// given
Pair<Deque<Span>, Map<String, String>> setupInfo = generateTracingInfo();
// when
Function result = (useStaticMethod)
? functionWithTracing(functionMock, setupInfo.getLeft(), setupInfo.getRight())
: DEFAULT_IMPL.functionWithTracing(functionMock,
setupInfo.getLeft(), setupInfo.getRight());
// then
verifyFunctionWithTracing(result, functionMock, setupInfo.getLeft(), setupInfo.getRight());
}
private Pair<Span, Map<String, String>> generateUpstreamSpanHeaders(boolean includeUserId) {
Span.Builder spanBuilder = Span.newBuilder("upstreamSpan", Span.SpanPurpose.CLIENT);
if (includeUserId) {
spanBuilder.withUserId("user-" + UUID.randomUUID().toString());
}
Span span = spanBuilder.build();
MapBuilder<String, String> headersBuilder = MapBuilder
.builder(TraceHeaders.TRACE_ID, span.getTraceId())
.put(TraceHeaders.SPAN_ID, span.getSpanId())
.put(TraceHeaders.SPAN_NAME, span.getSpanName())
.put(TraceHeaders.TRACE_SAMPLED, String.valueOf(span.isSampleable()));
if (span.getUserId() != null) {
headersBuilder.put(USER_ID_HEADER_KEY, span.getUserId());
}
return Pair.of(span, headersBuilder.build());
}
@DataProvider(value = {
"true",
"false"
})
@Test
public void current_thread_info_constructor_sets_fields_as_expected(boolean useStaticFactory) {
// given
Tracer.getInstance().startRequestWithRootSpan("request-" + UUID.randomUUID().toString());
Deque<Span> spanStackMock = Tracer.getInstance().getCurrentSpanStackCopy();
Map<String, String> mdcInfoMock = MDC.getCopyOfContextMap();
// when
CallableWithTracing instance = (useStaticFactory)
? withTracing(callableMock)
: new CallableWithTracing(callableMock);
// then
assertThat(instance.origCallable).isSameAs(callableMock);
assertThat(instance.spanStackForExecution).isEqualTo(spanStackMock);
assertThat(instance.mdcContextMapForExecution).isEqualTo(mdcInfoMock);
}
public static void verifyExpectedTracingHeaders(HttpRequest executedRequest, Span expectedSpanForHeaders) {
HttpHeaders headers = executedRequest.getHeaders();
List<String> actualTraceIdHeaderVal = headers.get(TRACE_ID);
List<String> actualSpanIdHeaderVal = headers.get(SPAN_ID);
List<String> actualSampledHeaderVal = headers.get(TRACE_SAMPLED);
List<String> actualParentSpanIdHeaderVal = headers.get(PARENT_SPAN_ID);
if (expectedSpanForHeaders == null) {
verifyExpectedTracingHeaderValue(actualTraceIdHeaderVal, null);
verifyExpectedTracingHeaderValue(actualSpanIdHeaderVal, null);
verifyExpectedTracingHeaderValue(actualSampledHeaderVal, null);
verifyExpectedTracingHeaderValue(actualParentSpanIdHeaderVal, null);
}
else {
verifyExpectedTracingHeaderValue(actualTraceIdHeaderVal, expectedSpanForHeaders.getTraceId());
verifyExpectedTracingHeaderValue(actualSpanIdHeaderVal, expectedSpanForHeaders.getSpanId());
verifyExpectedTracingHeaderValue(
actualSampledHeaderVal,
convertSampleableBooleanToExpectedB3Value(expectedSpanForHeaders.isSampleable())
);
verifyExpectedTracingHeaderValue(actualParentSpanIdHeaderVal, expectedSpanForHeaders.getParentSpanId());
}
}
@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);
}
private Pair<Span, Map<String, String>> generateUpstreamSpanHeaders(boolean includeUserId) {
Span.Builder spanBuilder = Span.newBuilder("upstreamSpan", Span.SpanPurpose.CLIENT);
if (includeUserId) {
spanBuilder.withUserId("user-" + UUID.randomUUID().toString());
}
Span span = spanBuilder.build();
MapBuilder<String, String> headersBuilder = MapBuilder
.builder(TraceHeaders.TRACE_ID, span.getTraceId())
.put(TraceHeaders.SPAN_ID, span.getSpanId())
.put(TraceHeaders.SPAN_NAME, span.getSpanName())
.put(TraceHeaders.TRACE_SAMPLED, String.valueOf(span.isSampleable()));
if (span.getUserId() != null) {
headersBuilder.put(USER_ID_HEADER_KEY, span.getUserId());
}
return Pair.of(span, headersBuilder.build());
}
private ResponseTaggingArgs(
Span span, REQ request, RES response, Throwable error,
HttpTagAndSpanNamingAdapter adapter
) {
this.span = span;
this.request = request;
this.response = response;
this.error = error;
this.adapter = adapter;
}
@DataProvider(value = {
"true",
"false"
}, splitBy = "\\|")
@Test
public void unlinkTracingFromCurrentThread_pair_works_as_expected(boolean useNullPair) {
// given
Pair<Deque<Span>, Map<String, String>> infoForLinking = (useNullPair) ? null
: generateTracingInfo();
// Setup the current thread with something that is not ultimately what we expect so that our assertions are
// verifying that the unlinkTracingFromCurrentThread method actually did something.
resetTracing();
Tracer.getInstance().startRequestWithRootSpan("foo-" + UUID.randomUUID().toString());
// when
unlinkTracingFromCurrentThread(infoForLinking);
Pair<Deque<Span>, Map<String, String>> postCallInfo = Pair.of(
Tracer.getInstance().getCurrentSpanStackCopy(),
MDC.getCopyOfContextMap()
);
// then
if (useNullPair) {
assertThat(postCallInfo.getLeft()).isNull();
assertThat(postCallInfo.getRight()).isNullOrEmpty();
}
else
assertThat(postCallInfo).isEqualTo(infoForLinking);
}
@SuppressWarnings("SameParameterValue")
protected void logErrorWithTracing(String msg, Throwable ex, ChannelHandlerContext ctx) {
Pair<Deque<Span>, Map<String, String>> tracingState =
AsyncNettyHelper.extractTracingAndMdcInfoFromChannelHandlerContext(ctx);
Deque<Span> distributedTraceStackToLink = null;
Map<String, String> mdcContextMapToLink = null;
if (tracingState != null) {
distributedTraceStackToLink = tracingState.getLeft();
mdcContextMapToLink = tracingState.getRight();
}
logErrorWithTracing(msg, ex, distributedTraceStackToLink, mdcContextMapToLink);
}
@DataProvider(value = {
"true",
"false"
})
@Test
public void linkTracingAndMdcToCurrentThread_pair_works_as_expected(boolean useNullPair) {
// given
Pair<Deque<Span>, Map<String, String>> infoForLinking = (useNullPair) ? null
: setupStateWithTracingAndMdcInfo();
resetTracingAndMdc();
Tracer.getInstance().startRequestWithRootSpan("foo-" + UUID.randomUUID().toString());
Pair<Deque<Span>, Map<String, String>> expectedPreCallInfo = Pair.of(
Tracer.getInstance().getCurrentSpanStackCopy(),
MDC.getCopyOfContextMap()
);
// when
Pair<Deque<Span>, Map<String, String>> preCallInfo =
AsyncNettyHelper.linkTracingAndMdcToCurrentThread(infoForLinking);
Pair<Deque<Span>, Map<String, String>> postCallInfo = Pair.of(
Tracer.getInstance().getCurrentSpanStackCopy(),
MDC.getCopyOfContextMap()
);
// then
assertThat(preCallInfo).isEqualTo(expectedPreCallInfo);
if (useNullPair)
assertThat(postCallInfo).isEqualTo(Pair.of(null, Collections.emptyMap()));
else
assertThat(postCallInfo).isEqualTo(infoForLinking);
}
@Override
public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
PipelineContinuationBehavior methodExecutionResponse;
boolean shouldLinkAndUnlinkDTraceInfo = shouldLinkAndUnlinkDistributedTraceInfoForMethod(
DO_CHANNEL_REGISTERED, isDefaultDoChannelRegisteredImpl, forceEnableDTraceOnAllMethods,
debugHandlerMethodCalls, ctx, null, null
);
Pair<Deque<Span>, Map<String, String>> origThreadInfo = null;
try {
if (shouldLinkAndUnlinkDTraceInfo)
origThreadInfo = linkTracingAndMdcToCurrentThread(ctx);
if (debugHandlerMethodCalls)
logger.debug("11111111111111 channelRegistered for {}", this.getClass().getName());
methodExecutionResponse = doChannelRegistered(ctx);
}
finally {
if (shouldLinkAndUnlinkDTraceInfo)
unlinkTracingAndMdcFromCurrentThread(ctx, origThreadInfo);
}
if (methodExecutionResponse == null || CONTINUE.equals(methodExecutionResponse))
super.channelRegistered(ctx);
}
public void verifyArgs(
Span expectedSpan, REQ expectedRequest, RES expectedResponse,
Throwable expectedError, HttpTagAndSpanNamingAdapter expectedAdapter
) {
assertThat(span).isSameAs(expectedSpan);
assertThat(request).isSameAs(expectedRequest);
assertThat(response).isSameAs(expectedResponse);
assertThat(error).isSameAs(expectedError);
assertThat(adapter).isSameAs(expectedAdapter);
}
@Test
public void constructors_throw_exception_if_passed_null_operator() {
// given
final Deque<Span> spanStackMock = mock(Deque.class);
final Map<String, String> mdcInfoMock = mock(Map.class);
// expect
assertThat(catchThrowable(() -> new FunctionWithTracing(null)))
.isInstanceOf(IllegalArgumentException.class);
assertThat(catchThrowable(() -> withTracing(null)))
.isInstanceOf(IllegalArgumentException.class);
// and expect
assertThat(catchThrowable(() -> new FunctionWithTracing(null, Pair.of(spanStackMock, mdcInfoMock))))
.isInstanceOf(IllegalArgumentException.class);
assertThat(catchThrowable(() -> withTracing(null, Pair.of(spanStackMock, mdcInfoMock))))
.isInstanceOf(IllegalArgumentException.class);
// and expect
assertThat(catchThrowable(() -> new FunctionWithTracing(null, spanStackMock, mdcInfoMock)))
.isInstanceOf(IllegalArgumentException.class);
assertThat(catchThrowable(() -> withTracing(null, spanStackMock, mdcInfoMock)))
.isInstanceOf(IllegalArgumentException.class);
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
PipelineContinuationBehavior methodExecutionResponse;
boolean shouldLinkAndUnlinkDTraceInfo = shouldLinkAndUnlinkDistributedTraceInfoForMethod(
DO_CHANNEL_READ, isDefaultDoChannelReadImpl, forceEnableDTraceOnAllMethods, debugHandlerMethodCalls,
ctx, msg, null
);
Pair<Deque<Span>, Map<String, String>> origThreadInfo = null;
try {
if (shouldLinkAndUnlinkDTraceInfo)
origThreadInfo = linkTracingAndMdcToCurrentThread(ctx);
if (debugHandlerMethodCalls)
logger.debug("############### channelRead for {}", this.getClass().getName());
methodExecutionResponse = doChannelRead(ctx, msg);
}
finally {
if (shouldLinkAndUnlinkDTraceInfo)
unlinkTracingAndMdcFromCurrentThread(ctx, origThreadInfo);
}
if (methodExecutionResponse == null || CONTINUE.equals(methodExecutionResponse))
super.channelRead(ctx, msg);
}
private Span findCompletedSpan(String expectedSpanName, String expectedSpanHandler) {
return spanRecorder.completedSpans
.stream()
.filter(
s -> s.getSpanName().equals(expectedSpanName)
&& expectedSpanHandler.equals(s.getTags().get(WingtipsTags.SPAN_HANDLER))
)
.findFirst()
.orElseThrow(
() -> new RuntimeException(
"Unable to find span with expected span name: " + expectedSpanName + " and span handler: "
+ expectedSpanHandler
)
);
}
@Test
public void WingtipsWebFilterTracingSubscriber_onComplete_calls_actual_subscriber_onComplete_and_completes_overall_request_span() {
// given
WingtipsWebFilterTracingSubscriber impl = setupSubscriberWrapper();
Span spanForCompletion = impl.overallRequestTracingState.spanStack.peek();
assertThat(spanForCompletion).isNotNull();
Tracer.getInstance().startRequestWithRootSpan("someRandomThreadRootSpan");
TracingState baseTracingState = TracingState.getCurrentThreadTracingState();
AtomicReference<TracingState> tracingStateOnActualOnComplete = new AtomicReference<>();
doAnswer(invocation -> {
tracingStateOnActualOnComplete.set(TracingState.getCurrentThreadTracingState());
return null;
}).when(impl.actual).onComplete();
assertThat(spanRecorder.completedSpans).isEmpty();
assertThat(spanForCompletion.isCompleted()).isFalse();
// when
impl.onComplete();
// then
verify(impl.actual).onComplete();
assertThat(tracingStateOnActualOnComplete.get()).isEqualTo(impl.overallRequestTracingState);
assertThat(strategyResponseTaggingAndFinalSpanNameMethodCalled.get()).isTrue();
strategyResponseTaggingArgs.get().verifyArgs(
spanForCompletion, exchange, responseMock, null, tagAndNamingAdapterMock
);
assertThat(spanForCompletion.isCompleted()).isTrue();
assertThat(spanRecorder.completedSpans).isEqualTo(singletonList(spanForCompletion));
// The current thread tracing state should be unchanged after the onComplete() call.
assertThat(TracingState.getCurrentThreadTracingState()).isEqualTo(baseTracingState);
}
@DataProvider(value = {
"SPAN_IS_NULL",
"ADAPTER_IS_NULL",
}, splitBy = "\\|")
@Test
@SuppressWarnings("ConstantConditions")
public void handleResponseTaggingAndFinalSpanName_does_nothing_in_null_arg_corner_cases(
NullArgCornerCaseScenario scenario
) {
// given
Span spanMock = scenario.spanMock;
HttpTagAndSpanNamingAdapter<Object, Object> adapterMock = scenario.adapterMock;
// when
implSpy.handleResponseTaggingAndFinalSpanName(
spanMock, requestObjectMock, responseObjectMock, errorMock, adapterMock
);
// then
verifyZeroInteractions(implSpy);
if (spanMock != null) {
verifyZeroInteractions(spanMock);
}
if (adapterMock != null) {
verifyZeroInteractions(adapterMock);
}
verifyZeroInteractions(requestObjectMock, responseObjectMock, errorMock);
}
@DataProvider(value = {
"true",
"false"
})
@Test
public void verify_blocking_forward_endpoint_traced_correctly(boolean upstreamSendsSpan) {
Pair<Span, Map<String, String>> upstreamSpanInfo = (upstreamSendsSpan)
? generateUpstreamSpanHeaders()
: Pair.of((Span)null, Collections.<String, String>emptyMap());
ExtractableResponse response =
given()
.baseUri("http://localhost")
.port(SERVER_PORT)
.headers(upstreamSpanInfo.getRight())
.queryParam("foo", "bar")
.log().all()
.when()
.get(BLOCKING_FORWARD_PATH)
.then()
.log().all()
.extract();
assertThat(response.statusCode()).isEqualTo(200);
assertThat(response.asString()).isEqualTo(BLOCKING_RESULT);
Span completedSpan =
verifySingleSpanCompletedAndReturnedInResponse(response, SLEEP_TIME_MILLIS * 2, upstreamSpanInfo.getLeft());
verifySpanNameAndTags(
completedSpan,
"GET",
"GET",
BLOCKING_FORWARD_PATH,
"http://localhost:" + SERVER_PORT + BLOCKING_FORWARD_PATH + "?foo=bar",
null,
response.statusCode(),
null,
"servlet"
);
}
@Override
public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
PipelineContinuationBehavior methodExecutionResponse;
boolean shouldLinkAndUnlinkDTraceInfo = shouldLinkAndUnlinkDistributedTraceInfoForMethod(
DO_HANDLER_REMOVED, isDefaultDoHandlerRemovedImpl, forceEnableDTraceOnAllMethods, debugHandlerMethodCalls,
ctx, null, null
);
Pair<Deque<Span>, Map<String, String>> origThreadInfo = null;
try {
if (shouldLinkAndUnlinkDTraceInfo)
origThreadInfo = linkTracingAndMdcToCurrentThread(ctx);
if (debugHandlerMethodCalls)
logger.debug("))))))))))))))))) handlerRemoved for {}", this.getClass().getName());
methodExecutionResponse = doHandlerRemoved(ctx);
}
finally {
if (shouldLinkAndUnlinkDTraceInfo)
unlinkTracingAndMdcFromCurrentThread(ctx, origThreadInfo);
}
if (methodExecutionResponse == null || CONTINUE.equals(methodExecutionResponse))
super.handlerRemoved(ctx);
}
@DataProvider(value = {
"true | true | true",
"true | false | true",
"false | true | true",
"false | false | true",
"true | true | false",
"true | false | false",
"false | true | false",
"false | false | false",
}, splitBy = "\\|")
@Test
public void pair_constructor_sets_fields_as_expected(
boolean nullSpanStack, boolean nullMdcInfo, boolean useStaticFactory
) {
// given
Deque<Span> spanStackMock = (nullSpanStack) ? null : mock(Deque.class);
Map<String, String> mdcInfoMock = (nullMdcInfo) ? null : mock(Map.class);
// when
CallableWithTracing instance = (useStaticFactory)
? withTracing(callableMock, Pair.of(spanStackMock, mdcInfoMock))
: new CallableWithTracing(callableMock, Pair.of(spanStackMock, mdcInfoMock)
);
// then
assertThat(instance.origCallable).isSameAs(callableMock);
assertThat(instance.spanStackForExecution).isEqualTo(spanStackMock);
assertThat(instance.mdcContextMapForExecution).isEqualTo(mdcInfoMock);
}
@DataProvider(value = {
"true | true | true",
"true | false | true",
"false | true | true",
"false | false | true",
"true | true | false",
"true | false | false",
"false | true | false",
"false | false | false",
}, splitBy = "\\|")
@Test
public void pair_constructor_sets_fields_as_expected(
boolean nullSpanStack, boolean nullMdcInfo, boolean useStaticFactory
) {
// given
Deque<Span> spanStackMock = (nullSpanStack) ? null : mock(Deque.class);
Map<String, String> mdcInfoMock = (nullMdcInfo) ? null : mock(Map.class);
// when
BiPredicateWithTracing instance = (useStaticFactory)
? withTracing(biPredicateMock, Pair.of(spanStackMock, mdcInfoMock))
: new BiPredicateWithTracing(biPredicateMock, Pair.of(spanStackMock, mdcInfoMock)
);
// then
assertThat(instance.origBiPredicate).isSameAs(biPredicateMock);
assertThat(instance.spanStackForExecution).isEqualTo(spanStackMock);
assertThat(instance.mdcContextMapForExecution).isEqualTo(mdcInfoMock);
}