Merge branch 'master' into 2.0.x
This commit is contained in:
@@ -20,16 +20,16 @@ import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.springframework.cloud.sleuth.zipkin.ZipkinSpanReporter;
|
||||
|
||||
import zipkin.Span;
|
||||
import zipkin2.Span;
|
||||
import zipkin2.reporter.Reporter;
|
||||
|
||||
/**
|
||||
* Span Collector that logs spans and adds Spans to a list
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
*/
|
||||
public class IntegrationTestZipkinSpanReporter implements ZipkinSpanReporter {
|
||||
public class IntegrationTestZipkinSpanReporter implements Reporter<Span> {
|
||||
|
||||
private static final Log log = org.apache.commons.logging.LogFactory
|
||||
.getLog(IntegrationTestZipkinSpanReporter.class);
|
||||
|
||||
@@ -15,12 +15,6 @@
|
||||
*/
|
||||
package integration;
|
||||
|
||||
import static java.util.concurrent.TimeUnit.SECONDS;
|
||||
import static org.assertj.core.api.BDDAssertions.then;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Random;
|
||||
@@ -31,7 +25,6 @@ import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.cloud.sleuth.zipkin.ZipkinSpanReporter;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
@@ -41,8 +34,11 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import integration.MessagingApplicationTests.IntegrationSpanCollectorConfig;
|
||||
import sample.SampleMessagingApplication;
|
||||
import tools.AbstractIntegrationTest;
|
||||
import zipkin.Constants;
|
||||
import zipkin.Span;
|
||||
import zipkin2.Span;
|
||||
import zipkin2.reporter.Reporter;
|
||||
|
||||
import static java.util.concurrent.TimeUnit.SECONDS;
|
||||
import static org.assertj.core.api.BDDAssertions.then;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@SpringBootTest(classes = { IntegrationSpanCollectorConfig.class, SampleMessagingApplication.class },
|
||||
@@ -82,7 +78,7 @@ public class MessagingApplicationTests extends AbstractIntegrationTest {
|
||||
httpMessageWithTraceIdInHeadersIsSuccessfullySent(sampleAppUrl + "/", traceId, spanId).run()
|
||||
);
|
||||
|
||||
await().atMost(5, SECONDS).untilAsserted(() -> {
|
||||
await().atMost(10, SECONDS).untilAsserted(() -> {
|
||||
thenAllSpansHaveTraceIdEqualTo(traceId);
|
||||
thenTheSpansHaveProperParentStructure();
|
||||
});
|
||||
@@ -98,79 +94,75 @@ public class MessagingApplicationTests extends AbstractIntegrationTest {
|
||||
|
||||
await().atMost(5, SECONDS).untilAsserted(() -> {
|
||||
thenAllSpansHaveTraceIdEqualTo(traceId);
|
||||
thenThereIsAtLeastOneBinaryAnnotationWithKey("background-sleep-millis");
|
||||
thenThereIsAtLeastOneTagWithKey("background-sleep-millis");
|
||||
});
|
||||
}
|
||||
|
||||
private void thenThereIsAtLeastOneBinaryAnnotationWithKey(String binaryAnnotationKey) {
|
||||
then(new ArrayList<>(this.integrationTestSpanCollector.hashedSpans).stream()
|
||||
.map(s -> s.binaryAnnotations)
|
||||
.flatMap(Collection::stream)
|
||||
.anyMatch(b -> b.key.equals(binaryAnnotationKey))).isTrue();
|
||||
private void thenThereIsAtLeastOneTagWithKey(String key) {
|
||||
then(this.integrationTestSpanCollector.hashedSpans.stream()
|
||||
.map(Span::tags)
|
||||
.flatMap(m -> m.keySet().stream())
|
||||
.anyMatch(b -> b.equals(key))).isTrue();
|
||||
}
|
||||
|
||||
private void thenAllSpansHaveTraceIdEqualTo(long traceId) {
|
||||
then(new ArrayList<>(this.integrationTestSpanCollector.hashedSpans).stream()
|
||||
.allMatch(span -> span.traceId == traceId)).describedAs("All spans have same trace id").isTrue();
|
||||
String traceIdHex = Long.toHexString(traceId);
|
||||
then(this.integrationTestSpanCollector.hashedSpans.stream()
|
||||
.allMatch(span -> span.traceId().equals(traceIdHex))).describedAs("All spans have same trace id").isTrue();
|
||||
}
|
||||
|
||||
private void thenTheSpansHaveProperParentStructure() {
|
||||
Optional<Span> firstHttpSpan = findFirstHttpRequestSpan();
|
||||
List<Span> eventSpans = findAllEventRelatedSpans();
|
||||
Optional<Span> eventSentSpan = findSpanWithAnnotation(Constants.SERVER_SEND);
|
||||
Optional<Span> eventReceivedSpan = findSpanWithAnnotation(Constants.CLIENT_RECV);
|
||||
Optional<Span> eventSentSpan = findSpanWithKind(Span.Kind.SERVER);
|
||||
Optional<Span> eventReceivedSpan = findSpanWithKind(Span.Kind.CLIENT);
|
||||
Optional<Span> lastHttpSpansParent = findLastHttpSpansParent();
|
||||
// "http:/parent/" -> "message:messages" -> "http:/foo" (CS + CR) -> "http:/foo" (SS)
|
||||
ArrayList<Span> spans = new ArrayList<>(
|
||||
this.integrationTestSpanCollector.hashedSpans);
|
||||
Collections.sort(spans);
|
||||
thenAllSpansArePresent(spans, firstHttpSpan, eventSpans, lastHttpSpansParent, eventSentSpan, eventReceivedSpan);
|
||||
then(spans).as("There were 4 spans").hasSize(4);
|
||||
thenAllSpansArePresent(firstHttpSpan, eventSpans, lastHttpSpansParent, eventSentSpan, eventReceivedSpan);
|
||||
then(this.integrationTestSpanCollector.hashedSpans).as("There were 4 spans").hasSize(4);
|
||||
log.info("Checking the parent child structure");
|
||||
List<Optional<Span>> parentChild = spans.stream()
|
||||
.filter(span -> span.parentId != null)
|
||||
.map(span -> spans.stream().filter(span1 -> span1.id == span.parentId).findAny()
|
||||
List<Optional<Span>> parentChild = this.integrationTestSpanCollector.hashedSpans.stream()
|
||||
.filter(span -> span.parentId() != null)
|
||||
.map(span -> this.integrationTestSpanCollector.hashedSpans.stream().filter(span1 -> span1.id().equals(span.parentId())).findAny()
|
||||
).collect(Collectors.toList());
|
||||
log.info("List of parents and children " + parentChild);
|
||||
then(parentChild.stream().allMatch(Optional::isPresent)).isTrue();
|
||||
}
|
||||
|
||||
private Optional<Span> findLastHttpSpansParent() {
|
||||
return new ArrayList<>(this.integrationTestSpanCollector.hashedSpans).stream()
|
||||
.filter(span -> "http:/foo".equals(span.name) && !span.annotations.isEmpty()).findFirst();
|
||||
return this.integrationTestSpanCollector.hashedSpans.stream()
|
||||
.filter(span -> "http:/foo".equals(span.name()) && span.kind() != null).findFirst();
|
||||
}
|
||||
|
||||
private Optional<Span> findSpanWithAnnotation(String annotationName) {
|
||||
return new ArrayList<>(this.integrationTestSpanCollector.hashedSpans).stream()
|
||||
.filter(span -> span.annotations.stream()
|
||||
.filter(annotation -> annotationName
|
||||
.equals(annotation.value)).findFirst().isPresent())
|
||||
private Optional<Span> findSpanWithKind(Span.Kind kind) {
|
||||
return this.integrationTestSpanCollector.hashedSpans.stream()
|
||||
.filter(span -> kind.equals(span.kind()))
|
||||
.findFirst();
|
||||
}
|
||||
|
||||
private List<Span> findAllEventRelatedSpans() {
|
||||
return new ArrayList<>(this.integrationTestSpanCollector.hashedSpans).stream()
|
||||
.filter(span -> "message:messages".equals(span.name) && span.parentId != null).collect(
|
||||
return this.integrationTestSpanCollector.hashedSpans.stream()
|
||||
.filter(span -> "message:messages".equals(span.name()) && span.parentId() != null).collect(
|
||||
Collectors.toList());
|
||||
}
|
||||
|
||||
private Optional<Span> findFirstHttpRequestSpan() {
|
||||
return new ArrayList<>(this.integrationTestSpanCollector.hashedSpans).stream()
|
||||
return this.integrationTestSpanCollector.hashedSpans.stream()
|
||||
// home is the name of the method
|
||||
.filter(span -> span.binaryAnnotations.stream()
|
||||
.anyMatch(binaryAnnotation -> new String(binaryAnnotation.value).equals("home"))).findFirst();
|
||||
.filter(span -> span.tags().values().stream()
|
||||
.anyMatch("home"::equals)).findFirst();
|
||||
}
|
||||
|
||||
private void thenAllSpansArePresent(ArrayList<Span> spans, Optional<Span> firstHttpSpan,
|
||||
List<Span> eventSpans, Optional<Span> lastHttpSpan, Optional<Span> eventSentSpan,
|
||||
Optional<Span> eventReceivedSpan) {
|
||||
private void thenAllSpansArePresent(Optional<Span> firstHttpSpan,
|
||||
List<Span> eventSpans, Optional<Span> lastHttpSpan,
|
||||
Optional<Span> eventSentSpan, Optional<Span> eventReceivedSpan) {
|
||||
log.info("Found following spans");
|
||||
log.info("First http span " + firstHttpSpan);
|
||||
log.info("Event spans " + eventSpans);
|
||||
log.info("Event sent span " + eventSentSpan);
|
||||
log.info("Event received span " + eventReceivedSpan);
|
||||
log.info("Last http span " + lastHttpSpan);
|
||||
log.info("All found spans \n" + spans
|
||||
log.info("All found spans \n" + this.integrationTestSpanCollector.hashedSpans
|
||||
.stream().map(Span::toString).collect(Collectors.joining("\n")));
|
||||
then(firstHttpSpan.isPresent()).isTrue();
|
||||
then(eventSpans).isNotEmpty();
|
||||
@@ -182,9 +174,8 @@ public class MessagingApplicationTests extends AbstractIntegrationTest {
|
||||
@Configuration
|
||||
public static class IntegrationSpanCollectorConfig {
|
||||
@Bean
|
||||
ZipkinSpanReporter integrationTestZipkinSpanReporter() {
|
||||
Reporter<Span> integrationTestZipkinSpanReporter() {
|
||||
return new IntegrationTestZipkinSpanReporter();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user