From bfe15ab0cd36ed41d659ed7dfb71d1e9ec6a7969 Mon Sep 17 00:00:00 2001 From: Adrian Cole Date: Fri, 27 Oct 2017 17:29:45 +0300 Subject: [PATCH] Misaligns Zipkin v1 from sharing the same version number as v2 (#760) This does two things: ensures samples don't use Zipkin v1 in any way, and misaligns the version numbers of zipkin v1 and zipkin v2 apis. This is an attempt to walk around the gradle plugin issue, which only exists when someone is using both versions of zipkin. See https://github.com/spring-projects/spring-boot/issues/10778 --- spring-cloud-sleuth-dependencies/pom.xml | 6 +- spring-cloud-sleuth-samples/pom.xml | 10 -- .../spring-cloud-sleuth-sample-feign/pom.xml | 2 +- .../java/sample/SampleFeignApplication.java | 8 +- .../pom.xml | 2 +- .../IntegrationTestZipkinSpanReporter.java | 6 +- .../MessagingApplicationTests.java | 47 +++---- .../spring-cloud-sleuth-sample-ribbon/pom.xml | 2 +- .../java/sample/SampleRibbonApplication.java | 8 +- .../pom.xml | 2 +- .../java/tools/AbstractIntegrationTest.java | 133 +----------------- .../pom.xml | 2 +- .../pom.xml | 13 +- .../test/java/integration/ZipkinTests.java | 95 ++++++++++--- spring-cloud-sleuth-zipkin/pom.xml | 4 + spring-cloud-sleuth-zipkin2/pom.xml | 12 -- .../zipkin2/ZipkinDiscoveryClientTests.java | 15 +- 17 files changed, 127 insertions(+), 240 deletions(-) diff --git a/spring-cloud-sleuth-dependencies/pom.xml b/spring-cloud-sleuth-dependencies/pom.xml index 7a56551dd..2dedde5de 100644 --- a/spring-cloud-sleuth-dependencies/pom.xml +++ b/spring-cloud-sleuth-dependencies/pom.xml @@ -14,7 +14,9 @@ spring-cloud-sleuth-dependencies Spring Cloud Sleuth Dependencies - 2.2.1 + + 2.2.0 + 2.2.1 1.1.2 2.1.3 @@ -73,7 +75,7 @@ io.zipkin.zipkin2 zipkin - ${zipkin.version} + ${zipkin2.version} io.zipkin.java diff --git a/spring-cloud-sleuth-samples/pom.xml b/spring-cloud-sleuth-samples/pom.xml index 1a18a656e..c041b9129 100644 --- a/spring-cloud-sleuth-samples/pom.xml +++ b/spring-cloud-sleuth-samples/pom.xml @@ -54,21 +54,11 @@ spring-cloud-sleuth-sample-test-core ${project.version} - - io.zipkin.java - zipkin - 2.2.1 - io.zipkin.zipkin2 zipkin 2.2.1 - - io.zipkin.java - zipkin-server - 2.2.1 - diff --git a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-feign/pom.xml b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-feign/pom.xml index 62d0a3d70..a9506c635 100644 --- a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-feign/pom.xml +++ b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-feign/pom.xml @@ -68,7 +68,7 @@ org.springframework.cloud - spring-cloud-sleuth-zipkin + spring-cloud-sleuth-zipkin2 org.springframework.boot diff --git a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-feign/src/main/java/sample/SampleFeignApplication.java b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-feign/src/main/java/sample/SampleFeignApplication.java index 7b6eacb11..74c54a855 100644 --- a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-feign/src/main/java/sample/SampleFeignApplication.java +++ b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-feign/src/main/java/sample/SampleFeignApplication.java @@ -22,10 +22,10 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.cloud.netflix.feign.EnableFeignClients; -import org.springframework.cloud.sleuth.zipkin.ZipkinSpanReporter; import org.springframework.context.annotation.Bean; -import zipkin.Span; +import zipkin2.Span; +import zipkin2.reporter.Reporter; /** * @author Spencer Gibb @@ -43,8 +43,8 @@ public class SampleFeignApplication { // Use this for debugging (or if there is no Zipkin server running on port 9411) @Bean @ConditionalOnProperty(value = "sample.zipkin.enabled", havingValue = "false") - public ZipkinSpanReporter spanCollector() { - return new ZipkinSpanReporter() { + public Reporter spanReporter() { + return new Reporter() { @Override public void report(Span span) { logger.info(span); diff --git a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-messaging/pom.xml b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-messaging/pom.xml index 5380ce6be..7b36713e6 100644 --- a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-messaging/pom.xml +++ b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-messaging/pom.xml @@ -82,7 +82,7 @@ org.springframework.cloud - spring-cloud-sleuth-zipkin + spring-cloud-sleuth-zipkin2 org.springframework.boot diff --git a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-messaging/src/test/java/integration/IntegrationTestZipkinSpanReporter.java b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-messaging/src/test/java/integration/IntegrationTestZipkinSpanReporter.java index a8774e550..dee6a7df3 100644 --- a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-messaging/src/test/java/integration/IntegrationTestZipkinSpanReporter.java +++ b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-messaging/src/test/java/integration/IntegrationTestZipkinSpanReporter.java @@ -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 { private static final Log log = org.apache.commons.logging.LogFactory .getLog(IntegrationTestZipkinSpanReporter.class); diff --git a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-messaging/src/test/java/integration/MessagingApplicationTests.java b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-messaging/src/test/java/integration/MessagingApplicationTests.java index 611492637..17fb1f0e2 100644 --- a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-messaging/src/test/java/integration/MessagingApplicationTests.java +++ b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-messaging/src/test/java/integration/MessagingApplicationTests.java @@ -15,8 +15,6 @@ */ package integration; -import java.util.Collection; -import java.util.Collections; import java.util.List; import java.util.Optional; import java.util.Random; @@ -27,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; @@ -37,8 +34,8 @@ 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; @@ -81,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(); }); @@ -97,36 +94,36 @@ 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) { + private void thenThereIsAtLeastOneTagWithKey(String key) { then(this.integrationTestSpanCollector.hashedSpans.stream() - .map(s -> s.binaryAnnotations) - .flatMap(Collection::stream) - .anyMatch(b -> b.key.equals(binaryAnnotationKey))).isTrue(); + .map(Span::tags) + .flatMap(m -> m.keySet().stream()) + .anyMatch(b -> b.equals(key))).isTrue(); } private void thenAllSpansHaveTraceIdEqualTo(long traceId) { + String traceIdHex = Long.toHexString(traceId); then(this.integrationTestSpanCollector.hashedSpans.stream() - .allMatch(span -> span.traceId == traceId)).describedAs("All spans have same trace id").isTrue(); + .allMatch(span -> span.traceId().equals(traceIdHex))).describedAs("All spans have same trace id").isTrue(); } private void thenTheSpansHaveProperParentStructure() { Optional firstHttpSpan = findFirstHttpRequestSpan(); List eventSpans = findAllEventRelatedSpans(); - Optional eventSentSpan = findSpanWithAnnotation(Constants.SERVER_SEND); - Optional eventReceivedSpan = findSpanWithAnnotation(Constants.CLIENT_RECV); + Optional eventSentSpan = findSpanWithKind(Span.Kind.SERVER); + Optional eventReceivedSpan = findSpanWithKind(Span.Kind.CLIENT); Optional lastHttpSpansParent = findLastHttpSpansParent(); // "http:/parent/" -> "message:messages" -> "http:/foo" (CS + CR) -> "http:/foo" (SS) - Collections.sort(this.integrationTestSpanCollector.hashedSpans); 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> parentChild = this.integrationTestSpanCollector.hashedSpans.stream() - .filter(span -> span.parentId != null) - .map(span -> this.integrationTestSpanCollector.hashedSpans.stream().filter(span1 -> span1.id == span.parentId).findAny() + .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(); @@ -134,27 +131,26 @@ public class MessagingApplicationTests extends AbstractIntegrationTest { private Optional findLastHttpSpansParent() { return this.integrationTestSpanCollector.hashedSpans.stream() - .filter(span -> "http:/foo".equals(span.name) && !span.annotations.isEmpty()).findFirst(); + .filter(span -> "http:/foo".equals(span.name()) && span.kind() != null).findFirst(); } - private Optional findSpanWithAnnotation(String annotationName) { + private Optional findSpanWithKind(Span.Kind kind) { return this.integrationTestSpanCollector.hashedSpans.stream() - .filter(span -> span.annotations.stream().filter(annotation -> annotationName - .equals(annotation.value)).findFirst().isPresent()) + .filter(span -> kind.equals(span.kind())) .findFirst(); } private List findAllEventRelatedSpans() { return this.integrationTestSpanCollector.hashedSpans.stream() - .filter(span -> "message:messages".equals(span.name) && span.parentId != null).collect( + .filter(span -> "message:messages".equals(span.name()) && span.parentId() != null).collect( Collectors.toList()); } private Optional findFirstHttpRequestSpan() { 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(Optional firstHttpSpan, @@ -178,9 +174,8 @@ public class MessagingApplicationTests extends AbstractIntegrationTest { @Configuration public static class IntegrationSpanCollectorConfig { @Bean - ZipkinSpanReporter integrationTestZipkinSpanReporter() { + Reporter integrationTestZipkinSpanReporter() { return new IntegrationTestZipkinSpanReporter(); } } - } diff --git a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-ribbon/pom.xml b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-ribbon/pom.xml index 13e63c2bc..0d7c1bbbc 100644 --- a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-ribbon/pom.xml +++ b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-ribbon/pom.xml @@ -70,7 +70,7 @@ org.springframework.cloud - spring-cloud-sleuth-zipkin + spring-cloud-sleuth-zipkin2 org.springframework.boot diff --git a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-ribbon/src/main/java/sample/SampleRibbonApplication.java b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-ribbon/src/main/java/sample/SampleRibbonApplication.java index ff4a0c18b..99850932a 100644 --- a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-ribbon/src/main/java/sample/SampleRibbonApplication.java +++ b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-ribbon/src/main/java/sample/SampleRibbonApplication.java @@ -22,12 +22,12 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.cloud.netflix.zuul.EnableZuulProxy; -import org.springframework.cloud.sleuth.zipkin.ZipkinSpanReporter; import org.springframework.context.annotation.Bean; import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.web.client.RestTemplate; -import zipkin.Span; +import zipkin2.Span; +import zipkin2.reporter.Reporter; /** * @author Spencer Gibb @@ -51,8 +51,8 @@ public class SampleRibbonApplication { // Use this for debugging (or if there is no Zipkin server running on port 9411) @Bean @ConditionalOnProperty(value = "sample.zipkin.enabled", havingValue = "false") - public ZipkinSpanReporter spanCollector() { - return new ZipkinSpanReporter() { + public Reporter spanReporter() { + return new Reporter() { @Override public void report(Span span) { logger.info(span); diff --git a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-test-core/pom.xml b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-test-core/pom.xml index 8aa15f999..4f9aae2c6 100644 --- a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-test-core/pom.xml +++ b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-test-core/pom.xml @@ -105,7 +105,7 @@ compile - io.zipkin.java + io.zipkin.zipkin2 zipkin diff --git a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-test-core/src/main/java/tools/AbstractIntegrationTest.java b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-test-core/src/main/java/tools/AbstractIntegrationTest.java index 69c544936..d0a73c0e9 100644 --- a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-test-core/src/main/java/tools/AbstractIntegrationTest.java +++ b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-test-core/src/main/java/tools/AbstractIntegrationTest.java @@ -15,18 +15,7 @@ */ package tools; -import zipkin.Codec; -import zipkin.Span; - import java.lang.invoke.MethodHandles; -import java.net.URI; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Optional; -import java.util.stream.Collectors; - import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.awaitility.Awaitility; @@ -34,15 +23,9 @@ import org.awaitility.core.ConditionFactory; import org.junit.After; import org.junit.Before; import org.springframework.cloud.sleuth.trace.IntegrationTestSpanContextHolder; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpMethod; -import org.springframework.http.HttpStatus; -import org.springframework.http.RequestEntity; -import org.springframework.http.ResponseEntity; import org.springframework.web.client.RestTemplate; import static java.util.concurrent.TimeUnit.SECONDS; -import static org.assertj.core.api.BDDAssertions.then; /** * @author Marcin Grzejszczak @@ -65,57 +48,6 @@ public abstract class AbstractIntegrationTest { IntegrationTestSpanContextHolder.removeCurrentSpan(); } - public static ConditionFactory await() { - return Awaitility.await().pollInterval(POLL_INTERVAL, SECONDS).atMost(TIMEOUT, SECONDS); - } - - protected Runnable zipkinServerIsUp() { - return checkServerHealth("Zipkin Stream Server", this::endpointToCheckZipkinServerHealth); - } - - protected Runnable checkServerHealth(String appName, RequestExchanger requestExchanger) { - return () -> { - ResponseEntity response = requestExchanger.exchange(); - log.info(String.format("Response from the [%s] health endpoint is [%s]", appName, response)); - then(response.getStatusCode()).isEqualTo(HttpStatus.OK); - log.info(String.format("[%s] is up!", appName)); - }; - } - - private interface RequestExchanger { - ResponseEntity exchange(); - } - - protected ResponseEntity endpointToCheckZipkinServerHealth() { - URI uri = URI.create("http://localhost:" +getZipkinServerPort()+"/health"); - log.info(String.format("Sending request to the Zipkin Server [%s]", uri)); - return exchangeRequest(uri); - } - - protected int getZipkinServerPort() { - return 9411; - } - - protected ResponseEntity checkStateOfTheTraceId(long traceId) { - URI uri = URI.create(getZipkinTraceQueryUrl() + Long.toHexString(traceId)); - log.info(String.format("Sending request to the Zipkin query service [%s]. " - + "Checking presence of trace id [%d]", uri, traceId)); - return exchangeRequest(uri); - } - - protected ResponseEntity exchangeRequest(URI uri) { - return this.restTemplate.exchange( - new RequestEntity<>(new HttpHeaders(), HttpMethod.GET, uri), String.class - ); - } - - protected String getZipkinTraceQueryUrl() { - return "http://localhost:"+getZipkinServerPort()+"/api/v1/trace/"; - } - - protected String getZipkinServicesQueryUrl() { - return "http://localhost:"+getZipkinServerPort()+"/api/v1/services"; - } protected Runnable httpMessageWithTraceIdInHeadersIsSuccessfullySent(String endpoint, long traceId) { return new RequestSendingRunnable(this.restTemplate, endpoint, traceId, null); @@ -125,68 +57,7 @@ public abstract class AbstractIntegrationTest { return new RequestSendingRunnable(this.restTemplate, endpoint, traceId, spanId); } - protected Runnable allSpansWereRegisteredInZipkinWithTraceIdEqualTo(long traceId) { - return () -> { - ResponseEntity response = checkStateOfTheTraceId(traceId); - log.info(String.format("Response from the Zipkin query service about the " - + "trace id [%s] for trace with id [%d]", response, traceId)); - then(response.getStatusCode()).isEqualTo(HttpStatus.OK); - then(response.hasBody()).isTrue(); - List spans = Codec.JSON.readSpans(response.getBody().getBytes()); - List serviceNamesNotFoundInZipkin = serviceNamesNotFoundInZipkin(spans); - List spanNamesNotFoundInZipkin = annotationsNotFoundInZipkin(spans); - log.info(String.format("The following services were not found in Zipkin [%s]", serviceNamesNotFoundInZipkin)); - log.info(String.format("The following annotations were not found in Zipkin [%s]", spanNamesNotFoundInZipkin)); - then(serviceNamesNotFoundInZipkin).isEmpty(); - then(spanNamesNotFoundInZipkin).isEmpty(); - log.info("Zipkin tracing is working! Sleuth is working! Let's be happy!"); - }; + public static ConditionFactory await() { + return Awaitility.await().pollInterval(POLL_INTERVAL, SECONDS).atMost(TIMEOUT, SECONDS); } - - protected List serviceNamesNotFoundInZipkin(List spans) { - List serviceNamesFoundInAnnotations = spans.stream() - .filter(span -> span.annotations != null) - .map(span -> span.annotations) - .flatMap(Collection::stream) - .filter(span -> span.endpoint != null) - .map(annotation -> annotation.endpoint) - .map(endpoint -> endpoint.serviceName) - .distinct() - .collect(Collectors.toList()); - List serviceNamesFoundInBinaryAnnotations = spans.stream() - .filter(span -> span.binaryAnnotations != null) - .map(span -> span.binaryAnnotations) - .flatMap(Collection::stream) - .filter(span -> span.endpoint != null) - .map(annotation -> annotation.endpoint) - .map(endpoint -> endpoint.serviceName) - .distinct() - .collect(Collectors.toList()); - List names = new ArrayList<>(); - names.addAll(serviceNamesFoundInAnnotations); - names.addAll(serviceNamesFoundInBinaryAnnotations); - return names.contains(getAppName()) ? Collections.emptyList() : names; - } - - protected String getAppName() { - return "unknown"; - } - - protected List annotationsNotFoundInZipkin(List spans) { - String binaryAnnotationName = getRequiredBinaryAnnotationName(); - Optional names = spans.stream() - .filter(span -> span.binaryAnnotations != null) - .map(span -> span.binaryAnnotations) - .flatMap(Collection::stream) - .filter(span -> span.endpoint != null) - .map(annotation -> annotation.key) - .filter(binaryAnnotationName::equals) - .findFirst(); - return names.isPresent() ? Collections.emptyList() : Collections.singletonList(binaryAnnotationName); - } - - protected String getRequiredBinaryAnnotationName() { - return "random-sleep-millis"; - } - } diff --git a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-websocket/pom.xml b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-websocket/pom.xml index 1720e7335..e6213b62c 100644 --- a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-websocket/pom.xml +++ b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-websocket/pom.xml @@ -82,7 +82,7 @@ org.springframework.cloud - spring-cloud-sleuth-zipkin + spring-cloud-sleuth-zipkin2 org.springframework.boot diff --git a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-zipkin2/pom.xml b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-zipkin2/pom.xml index 776b0fd75..46f2afc53 100644 --- a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-zipkin2/pom.xml +++ b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-zipkin2/pom.xml @@ -97,20 +97,9 @@ spring-cloud-sleuth-sample-test-core test - - io.zipkin.java - zipkin-server - test - - - io.zipkin.java - zipkin-junit - test - - com.squareup.okhttp3 - okhttp + mockwebserver 3.9.0 test diff --git a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-zipkin2/src/test/java/integration/ZipkinTests.java b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-zipkin2/src/test/java/integration/ZipkinTests.java index fbbf8e959..2d8e3f963 100644 --- a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-zipkin2/src/test/java/integration/ZipkinTests.java +++ b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-zipkin2/src/test/java/integration/ZipkinTests.java @@ -16,10 +16,17 @@ package integration; import integration.ZipkinTests.WaitUntilZipkinIsUpConfig; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.stream.Collectors; +import okhttp3.mockwebserver.MockResponse; +import okhttp3.mockwebserver.MockWebServer; +import okhttp3.mockwebserver.RecordedRequest; import sample.SampleZipkinApplication; import tools.AbstractIntegrationTest; -import zipkin.junit.ZipkinRule; -import zipkin.server.EnableZipkinServer; import java.net.URI; import java.util.Random; @@ -29,8 +36,6 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.cloud.sleuth.zipkin2.ZipkinProperties; import org.springframework.context.annotation.Bean; @@ -38,16 +43,18 @@ import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import zipkin2.Span; +import zipkin2.codec.SpanBytesDecoder; import static java.util.concurrent.TimeUnit.SECONDS; +import static org.assertj.core.api.BDDAssertions.then; @RunWith(SpringJUnit4ClassRunner.class) @SpringBootTest(classes = { WaitUntilZipkinIsUpConfig.class, SampleZipkinApplication.class }, webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) @TestPropertySource(properties = {"sample.zipkin.enabled=true"}) public class ZipkinTests extends AbstractIntegrationTest { - - @ClassRule public static final ZipkinRule zipkin = new ZipkinRule(); + @ClassRule public static final MockWebServer zipkin = new MockWebServer(); private static final String APP_NAME = "testsleuthzipkin"; @Value("${local.server.port}") @@ -55,7 +62,7 @@ public class ZipkinTests extends AbstractIntegrationTest { private String sampleAppUrl = "http://localhost:" + this.port; @Autowired ZipkinProperties zipkinProperties; - @Override protected int getZipkinServerPort() { + int getZipkinServerPort() { return getPortFromProps(); } @@ -64,21 +71,20 @@ public class ZipkinTests extends AbstractIntegrationTest { } @Test - public void should_propagate_spans_to_zipkin() { + public void should_propagate_spans_to_zipkin() throws Exception { + zipkin.enqueue(new MockResponse()); + long traceId = new Random().nextLong(); await().atMost(10, SECONDS).untilAsserted(() -> httpMessageWithTraceIdInHeadersIsSuccessfullySent( - this.sampleAppUrl + "/hi2", traceId).run() + this.sampleAppUrl + "/hi2", traceId).run() ); - await().atMost(10, SECONDS).untilAsserted(() -> - allSpansWereRegisteredInZipkinWithTraceIdEqualTo(traceId).run() - ); + spansSentToZipkin(zipkin, traceId); } - @Override - protected String getAppName() { + String getAppName() { return APP_NAME; } @@ -89,16 +95,63 @@ public class ZipkinTests extends AbstractIntegrationTest { @Primary ZipkinProperties testZipkinProperties() { ZipkinProperties zipkinProperties = new ZipkinProperties(); - zipkinProperties.setBaseUrl(zipkin.httpUrl()); + zipkinProperties.setBaseUrl(zipkin.url("/").toString()); return zipkinProperties; } } - @SpringBootApplication - @EnableZipkinServer - protected static class ZipkinServer { - public static void main(String[] args) { - SpringApplication.run(ZipkinServer.class, args); - } + void spansSentToZipkin(MockWebServer zipkin, long traceId) + throws InterruptedException { + RecordedRequest request = zipkin.takeRequest(); + List spans = SpanBytesDecoder.JSON_V2.decodeList(request.getBody().readByteArray()); + List traceIdsNotFoundInZipkin = traceIdsNotFoundInZipkin(spans, traceId); + List serviceNamesNotFoundInZipkin = serviceNamesNotFoundInZipkin(spans); + List tagsNotFoundInZipkin = hasRequiredTag(spans); + log.info(String.format("The following trace IDs were not found in Zipkin [%s]", traceIdsNotFoundInZipkin)); + log.info(String.format("The following services were not found in Zipkin [%s]", serviceNamesNotFoundInZipkin)); + log.info(String.format("The following tags were not found in Zipkin [%s]", tagsNotFoundInZipkin)); + then(traceIdsNotFoundInZipkin).isEmpty(); + then(serviceNamesNotFoundInZipkin).isEmpty(); + then(tagsNotFoundInZipkin).isEmpty(); + log.info("Zipkin tracing is working! Sleuth is working! Let's be happy!"); + } + + List traceIdsNotFoundInZipkin(List spans, long traceId) { + String traceIdString = Long.toHexString(traceId); + Optional traceIds = spans.stream() + .map(Span::traceId) + .filter(traceIdString::equals) + .findFirst(); + return traceIds.isPresent() ? Collections.emptyList() : Collections.singletonList(traceIdString); + } + + List serviceNamesNotFoundInZipkin(List spans) { + List localServiceNames = spans.stream() + .map(Span::localServiceName) + .filter(Objects::nonNull) + .distinct() + .collect(Collectors.toList()); + List remoteServiceNames = spans.stream() + .map(Span::remoteServiceName) + .filter(Objects::nonNull) + .distinct() + .collect(Collectors.toList()); + List names = new ArrayList<>(); + names.addAll(localServiceNames); + names.addAll(remoteServiceNames); + return names.contains(getAppName()) ? Collections.emptyList() : names; + } + + List hasRequiredTag(List spans) { + String key = getRequiredTagKey(); + Optional keys = spans.stream() + .flatMap(span -> span.tags().keySet().stream()) + .filter(key::equals) + .findFirst(); + return keys.isPresent() ? Collections.emptyList() : Collections.singletonList(key); + } + + String getRequiredTagKey() { + return "random-sleep-millis"; } } diff --git a/spring-cloud-sleuth-zipkin/pom.xml b/spring-cloud-sleuth-zipkin/pom.xml index dd5e7561c..5d5baf63e 100644 --- a/spring-cloud-sleuth-zipkin/pom.xml +++ b/spring-cloud-sleuth-zipkin/pom.xml @@ -69,6 +69,10 @@ io.zipkin.java zipkin + + io.zipkin.zipkin2 + zipkin + io.zipkin.reporter zipkin-reporter diff --git a/spring-cloud-sleuth-zipkin2/pom.xml b/spring-cloud-sleuth-zipkin2/pom.xml index 7266dc776..bcda3ecef 100644 --- a/spring-cloud-sleuth-zipkin2/pom.xml +++ b/spring-cloud-sleuth-zipkin2/pom.xml @@ -106,23 +106,11 @@ assertj-core test - - io.zipkin.java - zipkin-junit - test - org.awaitility awaitility test - - - com.squareup.okhttp3 - okhttp - 3.9.0 - test - com.squareup.okhttp3 mockwebserver diff --git a/spring-cloud-sleuth-zipkin2/src/test/java/org/springframework/cloud/sleuth/zipkin2/ZipkinDiscoveryClientTests.java b/spring-cloud-sleuth-zipkin2/src/test/java/org/springframework/cloud/sleuth/zipkin2/ZipkinDiscoveryClientTests.java index 9749e6929..b91af08f9 100644 --- a/spring-cloud-sleuth-zipkin2/src/test/java/org/springframework/cloud/sleuth/zipkin2/ZipkinDiscoveryClientTests.java +++ b/spring-cloud-sleuth-zipkin2/src/test/java/org/springframework/cloud/sleuth/zipkin2/ZipkinDiscoveryClientTests.java @@ -1,14 +1,12 @@ package org.springframework.cloud.sleuth.zipkin2; import static org.assertj.core.api.BDDAssertions.then; -import static org.springframework.cloud.sleuth.zipkin2.ZipkinDiscoveryClientTests.ZIPKIN_RULE; import java.io.IOException; import java.net.URI; -import java.util.Collections; -import java.util.List; import java.util.Map; +import okhttp3.mockwebserver.MockWebServer; import org.awaitility.Awaitility; import org.junit.ClassRule; import org.junit.Test; @@ -17,7 +15,6 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.cloud.client.ServiceInstance; -import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.cloud.client.loadbalancer.LoadBalancerClient; import org.springframework.cloud.client.loadbalancer.LoadBalancerRequest; import org.springframework.cloud.sleuth.Span; @@ -26,8 +23,6 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.test.context.junit4.SpringRunner; -import zipkin.junit.ZipkinRule; - @RunWith(SpringRunner.class) @SpringBootTest(classes = ZipkinDiscoveryClientTests.Config.class, properties = { "spring.zipkin.baseUrl=http://zipkin/", @@ -35,7 +30,7 @@ import zipkin.junit.ZipkinRule; }) public class ZipkinDiscoveryClientTests { - @ClassRule public static ZipkinRule ZIPKIN_RULE = new ZipkinRule(); + @ClassRule public static MockWebServer ZIPKIN_RULE = new MockWebServer(); @Autowired SpanReporter spanReporter; @@ -46,7 +41,7 @@ public class ZipkinDiscoveryClientTests { this.spanReporter.report(span); - Awaitility.await().untilAsserted(() -> then(ZIPKIN_RULE.httpRequestCount()).isGreaterThan(0)); + Awaitility.await().untilAsserted(() -> then(ZIPKIN_RULE.getRequestCount()).isGreaterThan(0)); } @Configuration @@ -85,7 +80,7 @@ public class ZipkinDiscoveryClientTests { @Override public int getPort() { - return URI.create(ZIPKIN_RULE.httpUrl()).getPort(); + return ZIPKIN_RULE.url("/").port(); } @Override @@ -95,7 +90,7 @@ public class ZipkinDiscoveryClientTests { @Override public URI getUri() { - return URI.create(ZIPKIN_RULE.httpUrl()); + return ZIPKIN_RULE.url("/").uri(); } @Override