@@ -16,8 +16,10 @@
|
||||
|
||||
package org.springframework.cloud.sleuth.instrument.web.client;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import org.springframework.cloud.sleuth.Span;
|
||||
import org.springframework.cloud.sleuth.SpanAccessor;
|
||||
import org.springframework.cloud.sleuth.Tracer;
|
||||
import org.springframework.cloud.sleuth.event.ClientReceivedEvent;
|
||||
import org.springframework.cloud.sleuth.event.ClientSentEvent;
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
@@ -38,10 +40,10 @@ abstract class AbstractTraceHttpRequestInterceptor
|
||||
implements ApplicationEventPublisherAware {
|
||||
|
||||
private ApplicationEventPublisher publisher;
|
||||
private final SpanAccessor accessor;
|
||||
protected final Tracer tracer;
|
||||
|
||||
protected AbstractTraceHttpRequestInterceptor(SpanAccessor accessor) {
|
||||
this.accessor = accessor;
|
||||
protected AbstractTraceHttpRequestInterceptor(Tracer tracer) {
|
||||
this.tracer = tracer;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -70,7 +72,7 @@ abstract class AbstractTraceHttpRequestInterceptor
|
||||
|
||||
private void setHeader(HttpRequest request, String name, String value) {
|
||||
if (StringUtils.hasText(value) && !request.getHeaders().containsKey(name) &&
|
||||
this.accessor.isTracing()) {
|
||||
this.tracer.isTracing()) {
|
||||
request.getHeaders().add(name, value);
|
||||
}
|
||||
}
|
||||
@@ -86,9 +88,11 @@ abstract class AbstractTraceHttpRequestInterceptor
|
||||
* the client sent event
|
||||
*/
|
||||
protected void publishStartEvent(HttpRequest request) {
|
||||
Span span = currentSpan();
|
||||
enrichWithTraceHeaders(request, span);
|
||||
publish(new ClientSentEvent(this, span));
|
||||
URI uri = request.getURI();
|
||||
String spanName = uri.getScheme() + ":" + uri.getPath();
|
||||
Span newSpan = this.tracer.startTrace(spanName);
|
||||
enrichWithTraceHeaders(request, newSpan);
|
||||
publish(new ClientSentEvent(this, newSpan));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -99,6 +103,7 @@ abstract class AbstractTraceHttpRequestInterceptor
|
||||
return;
|
||||
}
|
||||
publish(new ClientReceivedEvent(this, currentSpan()));
|
||||
this.tracer.close(this.currentSpan());
|
||||
}
|
||||
|
||||
private void publish(ApplicationEvent event) {
|
||||
@@ -108,11 +113,11 @@ abstract class AbstractTraceHttpRequestInterceptor
|
||||
}
|
||||
|
||||
private Span currentSpan() {
|
||||
return this.accessor.getCurrentSpan();
|
||||
return this.tracer.getCurrentSpan();
|
||||
}
|
||||
|
||||
protected boolean isTracing() {
|
||||
return this.accessor.isTracing();
|
||||
return this.tracer.isTracing();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -19,7 +19,6 @@ package org.springframework.cloud.sleuth.instrument.web.client;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
|
||||
import org.springframework.cloud.sleuth.SpanAccessor;
|
||||
import org.springframework.cloud.sleuth.Tracer;
|
||||
import org.springframework.core.task.AsyncListenableTaskExecutor;
|
||||
import org.springframework.http.HttpMethod;
|
||||
@@ -42,8 +41,7 @@ import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
|
||||
public class TraceAsyncClientHttpRequestFactoryWrapper extends AbstractTraceHttpRequestInterceptor
|
||||
implements ClientHttpRequestFactory, AsyncClientHttpRequestFactory {
|
||||
|
||||
private final Tracer tracer;
|
||||
private final AsyncClientHttpRequestFactory delegate;
|
||||
private final AsyncClientHttpRequestFactory asyncDelegate;
|
||||
private final ClientHttpRequestFactory syncDelegate;
|
||||
|
||||
/**
|
||||
@@ -55,32 +53,29 @@ public class TraceAsyncClientHttpRequestFactoryWrapper extends AbstractTraceHttp
|
||||
*
|
||||
* @see org.springframework.web.client.AsyncRestTemplate#AsyncRestTemplate(AsyncClientHttpRequestFactory)
|
||||
*/
|
||||
public TraceAsyncClientHttpRequestFactoryWrapper(SpanAccessor accessor, Tracer tracer,
|
||||
AsyncClientHttpRequestFactory delegate) {
|
||||
super(accessor);
|
||||
this.tracer = tracer;
|
||||
this.delegate = delegate;
|
||||
this.syncDelegate = delegate instanceof ClientHttpRequestFactory ?
|
||||
(ClientHttpRequestFactory) delegate : defaultClientHttpRequestFactory();
|
||||
public TraceAsyncClientHttpRequestFactoryWrapper(Tracer tracer,
|
||||
AsyncClientHttpRequestFactory asyncDelegate) {
|
||||
super(tracer);
|
||||
this.asyncDelegate = asyncDelegate;
|
||||
this.syncDelegate = asyncDelegate instanceof ClientHttpRequestFactory ?
|
||||
(ClientHttpRequestFactory) asyncDelegate : defaultClientHttpRequestFactory();
|
||||
}
|
||||
|
||||
/**
|
||||
* Default implementation that creates a {@link SimpleClientHttpRequestFactory} that
|
||||
* has a wrapped task executor via the {@link TraceAsyncListenableTaskExecutor}
|
||||
*/
|
||||
public TraceAsyncClientHttpRequestFactoryWrapper(SpanAccessor accessor, Tracer tracer) {
|
||||
super(accessor);
|
||||
this.tracer = tracer;
|
||||
public TraceAsyncClientHttpRequestFactoryWrapper(Tracer tracer) {
|
||||
super(tracer);
|
||||
SimpleClientHttpRequestFactory simpleClientHttpRequestFactory = defaultClientHttpRequestFactory();
|
||||
this.delegate = simpleClientHttpRequestFactory;
|
||||
this.asyncDelegate = simpleClientHttpRequestFactory;
|
||||
this.syncDelegate = simpleClientHttpRequestFactory;
|
||||
}
|
||||
|
||||
public TraceAsyncClientHttpRequestFactoryWrapper(SpanAccessor accessor, Tracer tracer,
|
||||
AsyncClientHttpRequestFactory delegate, ClientHttpRequestFactory syncDelegate) {
|
||||
super(accessor);
|
||||
this.tracer = tracer;
|
||||
this.delegate = delegate;
|
||||
public TraceAsyncClientHttpRequestFactoryWrapper(Tracer tracer,
|
||||
AsyncClientHttpRequestFactory asyncDelegate, ClientHttpRequestFactory syncDelegate) {
|
||||
super(tracer);
|
||||
this.asyncDelegate = asyncDelegate;
|
||||
this.syncDelegate = syncDelegate;
|
||||
}
|
||||
|
||||
@@ -99,7 +94,8 @@ public class TraceAsyncClientHttpRequestFactoryWrapper extends AbstractTraceHttp
|
||||
@Override
|
||||
public AsyncClientHttpRequest createAsyncRequest(URI uri, HttpMethod httpMethod)
|
||||
throws IOException {
|
||||
AsyncClientHttpRequest request = this.delegate.createAsyncRequest(uri, httpMethod);
|
||||
AsyncClientHttpRequest request = this.asyncDelegate
|
||||
.createAsyncRequest(uri, httpMethod);
|
||||
if (!isTracing()) {
|
||||
doNotSampleThisSpan(request);
|
||||
return request;
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright 2013-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.sleuth.instrument.web.client;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import org.springframework.cloud.sleuth.Span;
|
||||
import org.springframework.cloud.sleuth.Tracer;
|
||||
import org.springframework.cloud.sleuth.event.ClientReceivedEvent;
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.context.ApplicationEventPublisherAware;
|
||||
import org.springframework.core.task.AsyncListenableTaskExecutor;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.client.AsyncClientHttpRequestFactory;
|
||||
import org.springframework.http.client.ClientHttpRequestFactory;
|
||||
import org.springframework.util.concurrent.ListenableFuture;
|
||||
import org.springframework.web.client.AsyncRequestCallback;
|
||||
import org.springframework.web.client.AsyncRestTemplate;
|
||||
import org.springframework.web.client.ResponseExtractor;
|
||||
import org.springframework.web.client.RestClientException;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
/**
|
||||
* An {@link AsyncRestTemplate} that closes started spans when a response has been
|
||||
* successfully received.
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
class TraceAsyncRestTemplate extends AsyncRestTemplate
|
||||
implements ApplicationEventPublisherAware {
|
||||
|
||||
private ApplicationEventPublisher publisher;
|
||||
|
||||
private final Tracer tracer;
|
||||
|
||||
public TraceAsyncRestTemplate(Tracer tracer) {
|
||||
super();
|
||||
this.tracer = tracer;
|
||||
}
|
||||
|
||||
public TraceAsyncRestTemplate(AsyncListenableTaskExecutor taskExecutor, Tracer tracer) {
|
||||
super(taskExecutor);
|
||||
this.tracer = tracer;
|
||||
}
|
||||
|
||||
public TraceAsyncRestTemplate(AsyncClientHttpRequestFactory asyncRequestFactory,
|
||||
Tracer tracer) {
|
||||
super(asyncRequestFactory);
|
||||
this.tracer = tracer;
|
||||
}
|
||||
|
||||
public TraceAsyncRestTemplate(AsyncClientHttpRequestFactory asyncRequestFactory,
|
||||
ClientHttpRequestFactory syncRequestFactory, Tracer tracer) {
|
||||
super(asyncRequestFactory, syncRequestFactory);
|
||||
this.tracer = tracer;
|
||||
}
|
||||
|
||||
public TraceAsyncRestTemplate(AsyncClientHttpRequestFactory requestFactory,
|
||||
RestTemplate restTemplate, Tracer tracer) {
|
||||
super(requestFactory, restTemplate);
|
||||
this.tracer = tracer;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <T> ListenableFuture<T> doExecute(URI url, HttpMethod method,
|
||||
AsyncRequestCallback requestCallback, ResponseExtractor<T> responseExtractor)
|
||||
throws RestClientException {
|
||||
try {
|
||||
return super.doExecute(url, method, requestCallback, responseExtractor);
|
||||
} finally {
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
private void finish() {
|
||||
if (!isTracing()) {
|
||||
return;
|
||||
}
|
||||
publish(new ClientReceivedEvent(this, currentSpan()));
|
||||
this.tracer.close(this.currentSpan());
|
||||
}
|
||||
|
||||
private void publish(ApplicationEvent event) {
|
||||
if (this.publisher != null) {
|
||||
this.publisher.publishEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
private Span currentSpan() {
|
||||
return this.tracer.getCurrentSpan();
|
||||
}
|
||||
|
||||
private boolean isTracing() {
|
||||
return this.tracer.isTracing();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApplicationEventPublisher(
|
||||
ApplicationEventPublisher applicationEventPublisher) {
|
||||
this.publisher = applicationEventPublisher;
|
||||
}
|
||||
}
|
||||
@@ -20,6 +20,7 @@ import static java.util.Collections.singletonList;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Type;
|
||||
import java.net.URI;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
@@ -36,7 +37,6 @@ import org.springframework.cloud.netflix.feign.FeignAutoConfiguration;
|
||||
import org.springframework.cloud.netflix.feign.support.ResponseEntityDecoder;
|
||||
import org.springframework.cloud.netflix.feign.support.SpringDecoder;
|
||||
import org.springframework.cloud.sleuth.Span;
|
||||
import org.springframework.cloud.sleuth.SpanAccessor;
|
||||
import org.springframework.cloud.sleuth.Tracer;
|
||||
import org.springframework.cloud.sleuth.event.ClientReceivedEvent;
|
||||
import org.springframework.cloud.sleuth.event.ClientSentEvent;
|
||||
@@ -84,7 +84,7 @@ public class TraceFeignClientAutoConfiguration {
|
||||
private ApplicationEventPublisher publisher;
|
||||
|
||||
@Autowired
|
||||
private SpanAccessor accessor;
|
||||
private Tracer tracer;
|
||||
|
||||
@Bean
|
||||
@Scope("prototype")
|
||||
@@ -112,6 +112,7 @@ public class TraceFeignClientAutoConfiguration {
|
||||
Span span = getCurrentSpan();
|
||||
if (span != null) {
|
||||
publish(new ClientReceivedEvent(this, span));
|
||||
TraceFeignClientAutoConfiguration.this.tracer.close(span);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -123,7 +124,9 @@ public class TraceFeignClientAutoConfiguration {
|
||||
return new RequestInterceptor() {
|
||||
@Override
|
||||
public void apply(RequestTemplate template) {
|
||||
Span span = getCurrentSpan();
|
||||
URI uri = URI.create(template.url());
|
||||
String spanName = uri.getScheme() + ":" + uri.getPath();
|
||||
Span span = TraceFeignClientAutoConfiguration.this.tracer.startTrace(spanName);
|
||||
if (span == null) {
|
||||
setHeader(template, Span.NOT_SAMPLED_NAME, "true");
|
||||
return;
|
||||
@@ -156,7 +159,7 @@ public class TraceFeignClientAutoConfiguration {
|
||||
|
||||
public void setHeader(RequestTemplate request, String name, String value) {
|
||||
if (StringUtils.hasText(value) && !request.headers().containsKey(name)
|
||||
&& this.accessor.isTracing()) {
|
||||
&& this.tracer.isTracing()) {
|
||||
request.header(name, value);
|
||||
}
|
||||
}
|
||||
@@ -179,7 +182,7 @@ public class TraceFeignClientAutoConfiguration {
|
||||
public void setHeader(Map<String, Collection<String>> headers, String name,
|
||||
String value) {
|
||||
if (StringUtils.hasText(value) && !headers.containsKey(name)
|
||||
&& this.accessor.isTracing()) {
|
||||
&& this.tracer.isTracing()) {
|
||||
headers.put(name, singletonList(value));
|
||||
}
|
||||
}
|
||||
@@ -192,7 +195,7 @@ public class TraceFeignClientAutoConfiguration {
|
||||
}
|
||||
|
||||
private Span getCurrentSpan() {
|
||||
return this.accessor.getCurrentSpan();
|
||||
return this.tracer.getCurrentSpan();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ package org.springframework.cloud.sleuth.instrument.web.client;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.springframework.cloud.sleuth.SpanAccessor;
|
||||
import org.springframework.cloud.sleuth.Tracer;
|
||||
import org.springframework.http.HttpRequest;
|
||||
import org.springframework.http.client.ClientHttpRequestExecution;
|
||||
import org.springframework.http.client.ClientHttpRequestInterceptor;
|
||||
@@ -31,15 +31,14 @@ import org.springframework.http.client.ClientHttpResponse;
|
||||
* @author Spencer Gibb
|
||||
*
|
||||
* @see org.springframework.web.client.RestTemplate
|
||||
* @see SpanAccessor
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class TraceRestTemplateInterceptor extends AbstractTraceHttpRequestInterceptor
|
||||
implements ClientHttpRequestInterceptor {
|
||||
|
||||
public TraceRestTemplateInterceptor(SpanAccessor accessor) {
|
||||
super(accessor);
|
||||
public TraceRestTemplateInterceptor(Tracer tracer) {
|
||||
super(tracer);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -47,14 +47,15 @@ public class TraceWebAsyncClientAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public AsyncClientHttpRequestFactory asyncClientHttpRequestFactory(SpanAccessor spanAccessor, Tracer tracer) {
|
||||
return new TraceAsyncClientHttpRequestFactoryWrapper(spanAccessor, tracer);
|
||||
public AsyncClientHttpRequestFactory asyncClientHttpRequestFactory(Tracer tracer) {
|
||||
return new TraceAsyncClientHttpRequestFactoryWrapper(tracer);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public AsyncRestTemplate asyncRestTemplate(AsyncClientHttpRequestFactory asyncClientHttpRequestFactory) {
|
||||
return new AsyncRestTemplate(asyncClientHttpRequestFactory);
|
||||
public AsyncRestTemplate asyncRestTemplate(AsyncClientHttpRequestFactory asyncClientHttpRequestFactory,
|
||||
Tracer tracer) {
|
||||
return new TraceAsyncRestTemplate(asyncClientHttpRequestFactory, tracer);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.cloud.sleuth.SpanAccessor;
|
||||
import org.springframework.cloud.sleuth.Tracer;
|
||||
import org.springframework.cloud.sleuth.autoconfig.TraceAutoConfiguration;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
@@ -46,14 +46,14 @@ import org.springframework.web.client.RestTemplate;
|
||||
@Configuration
|
||||
@ConditionalOnProperty(value = "spring.sleuth.client.enabled", matchIfMissing = true)
|
||||
@ConditionalOnClass(RestTemplate.class)
|
||||
@ConditionalOnBean(SpanAccessor.class)
|
||||
@ConditionalOnBean(Tracer.class)
|
||||
@AutoConfigureAfter(TraceAutoConfiguration.class)
|
||||
public class TraceWebClientAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public TraceRestTemplateInterceptor traceRestTemplateInterceptor(SpanAccessor accessor) {
|
||||
return new TraceRestTemplateInterceptor(accessor);
|
||||
public TraceRestTemplateInterceptor traceRestTemplateInterceptor(Tracer tracer) {
|
||||
return new TraceRestTemplateInterceptor(tracer);
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
||||
@@ -90,15 +90,16 @@ public class FeignTraceTests {
|
||||
public void shouldAttachTraceIdWhenUsingFeignClient() {
|
||||
Long currentTraceId = 1L;
|
||||
Long currentParentId = 2L;
|
||||
Long currentSpanId = generatedId();
|
||||
this.tracer.continueSpan(Span.builder().traceId(currentTraceId)
|
||||
.spanId(generatedId()).parent(currentParentId).build());
|
||||
.spanId(currentSpanId).parent(currentParentId).build());
|
||||
|
||||
ResponseEntity<String> response = this.testFeignInterface.getTraceId();
|
||||
|
||||
then(Span.hexToId(getHeader(response, Span.TRACE_ID_NAME)))
|
||||
.isEqualTo(currentTraceId);
|
||||
then(Span.hexToId(getHeader(response, Span.PARENT_ID_NAME)))
|
||||
.isEqualTo(currentParentId);
|
||||
.isEqualTo(currentSpanId);
|
||||
then(this.listener.getEvents().size()).isEqualTo(2);
|
||||
}
|
||||
|
||||
|
||||
@@ -80,9 +80,9 @@ public class TraceRestTemplateInterceptorTests {
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, String> headers = this.template.getForEntity("/", Map.class)
|
||||
.getBody();
|
||||
then(Long.valueOf(headers.get(Span.TRACE_ID_NAME))).isEqualTo(1L);
|
||||
then(Long.valueOf(headers.get(Span.SPAN_ID_NAME))).isEqualTo(2L);
|
||||
then(Long.valueOf(headers.get(Span.PARENT_ID_NAME))).isEqualTo(3L);
|
||||
then(Span.hexToId(headers.get(Span.TRACE_ID_NAME))).isEqualTo(1L);
|
||||
then(Span.hexToId(headers.get(Span.SPAN_ID_NAME))).isNotEqualTo(2L);
|
||||
then(Span.hexToId(headers.get(Span.PARENT_ID_NAME))).isEqualTo(2L);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -91,8 +91,8 @@ public class TraceRestTemplateInterceptorTests {
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, String> headers = this.template.getForEntity("/", Map.class)
|
||||
.getBody();
|
||||
then(Long.valueOf(headers.get(Span.TRACE_ID_NAME))).isEqualTo(1L);
|
||||
then(Long.valueOf(headers.get(Span.SPAN_ID_NAME))).isEqualTo(2L);
|
||||
then(Span.hexToId(headers.get(Span.TRACE_ID_NAME))).isEqualTo(1L);
|
||||
then(Span.hexToId(headers.get(Span.SPAN_ID_NAME))).isNotEqualTo(2L);
|
||||
then(headers.get(Span.NOT_SAMPLED_NAME)).isEqualTo("true");
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
package integration;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Random;
|
||||
@@ -106,22 +107,32 @@ public class MessagingApplicationTests extends AbstractIntegrationTest {
|
||||
private void thenTheSpansHaveProperParentStructure() {
|
||||
Optional<Span> firstHttpSpan = findFirstHttpRequestSpan();
|
||||
List<Span> eventSpans = findAllEventRelatedSpans();
|
||||
Optional<Span> eventSentSpan = findSpanWithAnnotation(eventSpans, Constants.SERVER_SEND);
|
||||
Optional<Span> eventReceivedSpan = findSpanWithAnnotation(eventSpans, Constants.CLIENT_RECV);
|
||||
Optional<Span> lastHttpSpan = findLastHttpSpan();
|
||||
thenAllSpansArePresent(firstHttpSpan, eventSpans, lastHttpSpan, eventSentSpan, eventReceivedSpan);
|
||||
then(lastHttpSpan.get().parentId).isEqualTo(eventSentSpan.get().id);
|
||||
then(eventSentSpan.get().parentId).isEqualTo(firstHttpSpan.get().id);
|
||||
then(eventSentSpan.get()).isNotEqualTo(eventReceivedSpan.get());
|
||||
Optional<Span> eventSentSpan = findSpanWithAnnotation(Constants.SERVER_SEND);
|
||||
Optional<Span> eventReceivedSpan = findSpanWithAnnotation(Constants.CLIENT_RECV);
|
||||
Optional<Span> lastHttpSpansParent = findLastHttpSpansParent();
|
||||
thenAllSpansArePresent(firstHttpSpan, eventSpans, lastHttpSpansParent, eventSentSpan, eventReceivedSpan);
|
||||
// "http:/parent/" -> "http:/" -> "message:messages" -> "http:/foo" (CS + CR) -> "http:/foo" (SS) -> "http:/foo"
|
||||
Collections.sort(this.integrationTestSpanCollector.hashedSpans, (s1, s2) -> s1.timestamp.compareTo(s2.timestamp));
|
||||
then(this.integrationTestSpanCollector.hashedSpans).hasSize(6);
|
||||
for (int i=0; i<this.integrationTestSpanCollector.hashedSpans.size(); i++) {
|
||||
if (i - 1 >= 0) {
|
||||
Span parent = this.integrationTestSpanCollector.hashedSpans.get(i - 1);
|
||||
Span current = this.integrationTestSpanCollector.hashedSpans.get(i);
|
||||
// there is a pair of spans having cs/cr and ss/sr
|
||||
if (current.id != parent.id) {
|
||||
then(current.parentId).isEqualTo(parent.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Optional<Span> findLastHttpSpan() {
|
||||
private Optional<Span> findLastHttpSpansParent() {
|
||||
return this.integrationTestSpanCollector.hashedSpans.stream()
|
||||
.filter(span -> "http:/foo".equals(span.name)).findFirst();
|
||||
.filter(span -> "http:/foo".equals(span.name) && !span.annotations.isEmpty()).findFirst();
|
||||
}
|
||||
|
||||
private Optional<Span> findSpanWithAnnotation(List<Span> eventSpans, String annotationName) {
|
||||
return eventSpans.stream()
|
||||
private Optional<Span> findSpanWithAnnotation(String annotationName) {
|
||||
return this.integrationTestSpanCollector.hashedSpans.stream()
|
||||
.filter(span -> span.annotations.stream().filter(annotation -> annotationName
|
||||
.equals(annotation.value)).findFirst().isPresent())
|
||||
.findFirst();
|
||||
|
||||
Reference in New Issue
Block a user