diff --git a/README.adoc b/README.adoc index c1b10d72d..41236b0bb 100644 --- a/README.adoc +++ b/README.adoc @@ -37,7 +37,7 @@ logging: * Instruments common ingress and egress points from Spring applications (servlet filter, rest template, scheduled actions, message channels, zuul filters, feign client). -* If `spring-cloud-sleuth-zipkin` then the app will generate and collect Zipkin-compatible traces (using Brave). By default it sends them via Thrift to a Zipkin collector service on localhost (port 9410). Configure the location of the service using `spring.zipkin.[host,port]`. +* If `spring-cloud-sleuth-zipkin` then the app will generate and collect Zipkin-compatible traces (using Brave). By default it sends them via HTTP to a Zipkin server on localhost (port 9411). Configure the location of the service using `spring.zipkin.[host,port]`. * If `spring-cloud-sleuth-stream` then the app will generate and collect traces via Spring Cloud Stream. Your app automatically becomes a producer of tracer messages that are sent over your broker of choice (e.g. RabbitMQ, Apache Kafka, Redis). diff --git a/docs/src/main/asciidoc/README.adoc b/docs/src/main/asciidoc/README.adoc index ce1efe02d..f6511d2e2 100644 --- a/docs/src/main/asciidoc/README.adoc +++ b/docs/src/main/asciidoc/README.adoc @@ -25,7 +25,7 @@ The Ribbon sample makes an interesting demo or playground for learning about zip === Running samples with Zipkin 1. Optionally run the https://github.com/openzipkin/zipkin[Zipkin] UI, e.g. via docker compose (there's a `docker-compose.yml` in https://github.com/spring-cloud/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-zipkin[Spring Cloud Sleuth], or in https://github.com/openzipkin/docker-zipkin[Docker Zipkin] -7. Run the zipkin sample application (set `sample.zipkin.enabled=false` if you have no Zipkin running). If you are using a VM to run docker you might need to tunnel port 9410 to localhost, or change the `spring.zipkin.host`. +7. Run the zipkin sample application (set `sample.zipkin.enabled=false` if you have no Zipkin running). If you are using a VM to run docker you might need to tunnel port 9411 to localhost, or change the `spring.zipkin.host`. 8. Hit `http://localhost:3380`, `http://localhost:3380/call`, `http://localhost:3380/async` for some interesting sample traces (the app callas back to itself). 9. Goto `http://localhost:8080` for zipkin web (if you are using boot2docker the host will be different) @@ -37,7 +37,7 @@ image::https://raw.githubusercontent.com/spring-cloud/spring-cloud-sleuth/master === Running samples with Zipkin Stream -Instead of using the native (Scala) Zipkin collector server you can export your span data over https://raw.githubusercontent.com/spring-cloud/spring-cloud-stream[Spring Cloud Stream]. +Instead of POSTing trace data directly to a Zipkin server, you can export them over https://raw.githubusercontent.com/spring-cloud/spring-cloud-stream[Spring Cloud Stream]. 1. Build the Zipkin Stream sample with Maven and run it via its `docker-compose.yml` (which also starts the required middleware and the Zipkin UI). 7. Run the `spring-cloud-sleuth-sample-stream` app and interact with it in a browser, just like the vanilla sample. If you are using a VM to run docker you might need to tunnel port 5672 to localhost, or change the `spring.rabbbitmq.host`. diff --git a/docs/src/main/asciidoc/features.adoc b/docs/src/main/asciidoc/features.adoc index 36d22f711..0e9f91b80 100644 --- a/docs/src/main/asciidoc/features.adoc +++ b/docs/src/main/asciidoc/features.adoc @@ -17,6 +17,6 @@ logging: * Instruments common ingress and egress points from Spring applications (servlet filter, rest template, scheduled actions, message channels, zuul filters, feign client). -* If `spring-cloud-sleuth-zipkin` then the app will generate and collect Zipkin-compatible traces (using Brave). By default it sends them via Thrift to a Zipkin collector service on localhost (port 9410). Configure the location of the service using `spring.zipkin.[host,port]`. +* If `spring-cloud-sleuth-zipkin` then the app will generate and collect Zipkin-compatible traces (using Brave). By default it sends them via HTTP to a Zipkin server on localhost (port 9411). Configure the location of the service using `spring.zipkin.[host,port]`. -* If `spring-cloud-sleuth-stream` then the app will generate and collect traces via Spring Cloud Stream. Your app automatically becomes a producer of tracer messages that are sent over your broker of choice (e.g. RabbitMQ, Apache Kafka, Redis). \ No newline at end of file +* If `spring-cloud-sleuth-stream` then the app will generate and collect traces via Spring Cloud Stream. Your app automatically becomes a producer of tracer messages that are sent over your broker of choice (e.g. RabbitMQ, Apache Kafka, Redis). diff --git a/spring-cloud-sleuth-core/pom.xml b/spring-cloud-sleuth-core/pom.xml index 4d6c95003..64736db75 100644 --- a/spring-cloud-sleuth-core/pom.xml +++ b/spring-cloud-sleuth-core/pom.xml @@ -7,6 +7,18 @@ jar Spring Cloud Sleuth Core Spring Cloud Sleuth Core + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.8 + 1.8 + + + + org.springframework.cloud diff --git a/spring-cloud-sleuth-dependencies/pom.xml b/spring-cloud-sleuth-dependencies/pom.xml index 3d9f6b3b5..dac807076 100644 --- a/spring-cloud-sleuth-dependencies/pom.xml +++ b/spring-cloud-sleuth-dependencies/pom.xml @@ -14,10 +14,10 @@ spring-cloud-sleuth-dependencies Spring Cloud Sleuth Dependencies - 3.2.0 + 3.4.0 1.1.0.BUILD-SNAPSHOT 1.8.4 - 0.1.2 + 0.4.0 @@ -60,7 +60,7 @@ com.github.kristofa - brave-spancollector-scribe + brave-core ${brave.version} @@ -73,6 +73,11 @@ aspectjweaver ${aspectj.version} + + io.zipkin + zipkin-java-core + ${zipkin-java.version} + io.zipkin zipkin-java-server 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 82b8f8a0d..20b9f92a4 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 @@ -36,6 +36,14 @@ true + + org.apache.maven.plugins + maven-compiler-plugin + + 1.8 + 1.8 + + diff --git a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-messaging/src/main/java/sample/SampleMessagingApplication.java b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-messaging/src/main/java/sample/SampleMessagingApplication.java index ab529b2e0..b89f583a7 100644 --- a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-messaging/src/main/java/sample/SampleMessagingApplication.java +++ b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-messaging/src/main/java/sample/SampleMessagingApplication.java @@ -70,7 +70,7 @@ public class SampleMessagingApplication { SpringApplication.run(SampleMessagingApplication.class, args); } - // Use this for debugging (or if there is no Zipkin collector running on port 9410) + // Use this for debugging (or if there is no Zipkin server running on port 9411) @Bean @ConditionalOnProperty(value="sample.zipkin.enabled", havingValue="false") public SpanCollector spanCollector() { 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 f3a745a9e..7993591ad 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 @@ -47,7 +47,7 @@ public class SampleRibbonApplication { SpringApplication.run(SampleRibbonApplication.class, args); } - // Use this for debugging (or if there is no Zipkin collector running on port 9410) + // Use this for debugging (or if there is no Zipkin server running on port 9411) @Bean @ConditionalOnProperty(value="sample.zipkin.enabled", havingValue="false") public SpanCollector spanCollector() { 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 5899d8fbe..113b330bc 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 @@ -111,9 +111,8 @@ io.zipkin zipkin-java-core - 0.1.1 compile - \ No newline at end of file + 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 23f9e2390..581ae5cd0 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,21 +15,26 @@ */ package tools; +import com.github.kristofa.brave.EmptySpanCollectorMetricsHandler; +import com.github.kristofa.brave.HttpSpanCollector; import com.github.kristofa.brave.SpanCollector; -import com.github.kristofa.brave.scribe.ScribeSpanCollector; +import com.github.kristofa.brave.SpanCollectorMetricsHandler; import com.jayway.awaitility.Awaitility; import com.jayway.awaitility.core.ConditionFactory; +import java.net.URI; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import org.springframework.cloud.sleuth.zipkin.ZipkinProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.http.*; +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.util.StringUtils; import org.springframework.web.client.RestTemplate; -import java.net.URI; - import static java.util.concurrent.TimeUnit.SECONDS; import static org.assertj.core.api.BDDAssertions.then; @@ -93,30 +98,12 @@ public abstract class AbstractIntegrationTest { }; } - protected Runnable zipkinCollectorServerIsUp() { - return new Runnable() { - @Override - public void run() { - ResponseEntity response = endpointToCheckZipkinCollectorHealth(); - log.info("Response from the Zipkin collector's health endpoint is [{}]", response); - then(response.getStatusCode()).isEqualTo(HttpStatus.OK); - log.info("Zipkin collector server is up!"); - } - }; - } - protected ResponseEntity endpointToCheckZipkinQueryHealth() { URI uri = URI.create(getZipkinServicesQueryUrl()); log.info("Sending request to the Zipkin query service [{}]", uri); return exchangeRequest(uri); } - protected ResponseEntity endpointToCheckZipkinCollectorHealth() { - URI uri = URI.create(getZipkinCollectorHealthUrl()); - log.info("Sending request to the Zipkin collector service [{}]", uri); - return exchangeRequest(uri); - } - protected ResponseEntity checkStateOfTheTraceId(String traceId) { String hexTraceId = zipkinHashedHexStringTraceId(traceId); URI uri = URI.create(getZipkinTraceQueryUrl() + hexTraceId); @@ -138,10 +125,6 @@ public abstract class AbstractIntegrationTest { return getDockerUrl() + ":9411/api/v1/services"; } - protected String getZipkinCollectorHealthUrl() { - return getDockerUrl() + ":9900/health"; - } - @Configuration public static class Config { @Bean @@ -155,7 +138,7 @@ public abstract class AbstractIntegrationTest { public static class ZipkinConfig { @Bean @SneakyThrows - public ScribeSpanCollector spanCollector(final ZipkinProperties zipkin) { + public SpanCollector spanCollector(final ZipkinProperties zipkin) { await().until(new Runnable() { @Override public void run() { @@ -170,9 +153,11 @@ public abstract class AbstractIntegrationTest { return getSpanCollector(zipkin); } - private ScribeSpanCollector getSpanCollector(ZipkinProperties zipkin) { - return new ScribeSpanCollector(getDockerURI().getHost(), - zipkin.getPort(), zipkin.getCollector()); - } - } + private SpanCollector getSpanCollector(ZipkinProperties zipkin) { + String url = "http://" + getDockerURI().getHost() + ":" + zipkin.getPort(); + // TODO: parameterize this + SpanCollectorMetricsHandler metrics = new EmptySpanCollectorMetricsHandler(); + return HttpSpanCollector.create(url, zipkin.getHttpConfig(), metrics); + } + } } diff --git a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-zipkin-stream/docker-compose.yml b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-zipkin-stream/docker-compose.yml index 608092e32..5f49487a9 100644 --- a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-zipkin-stream/docker-compose.yml +++ b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-zipkin-stream/docker-compose.yml @@ -29,7 +29,7 @@ zipkin: - mysql - rabbitmq web: - image: openzipkin/zipkin-web:1.28.0 + image: openzipkin/zipkin-web:1.30.0 ports: - 8080:8080 environment: diff --git a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-zipkin-stream/src/main/resources/application.yml b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-zipkin-stream/src/main/resources/application.yml index b13101782..4f9aaa5f0 100644 --- a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-zipkin-stream/src/main/resources/application.yml +++ b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-zipkin-stream/src/main/resources/application.yml @@ -8,6 +8,10 @@ spring: initialize: false zipkin: + collector: + sample-rate: 1.0 # percentage to traces to retain + query: + lookback: 86400000 # 7 days in millis store: type: mem # default is inMemory diff --git a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-zipkin/docker-compose.yml b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-zipkin/docker-compose.yml index 278e87ce8..5375fd21c 100644 --- a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-zipkin/docker-compose.yml +++ b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-zipkin/docker-compose.yml @@ -1,21 +1,9 @@ mysql: - image: openzipkin/zipkin-mysql:1.28.0 + image: openzipkin/zipkin-mysql:1.30.0 ports: - 3306:3306 -collector: - image: openzipkin/zipkin-collector:1.28.0 - environment: - - TRANSPORT_TYPE=scribe - - STORAGE_TYPE=mysql - expose: - - 9410 - ports: - - 9410:9410 - - 9900:9900 - links: - - mysql:storage query: - image: openzipkin/zipkin-query:1.28.0 + image: openzipkin/zipkin-query:1.30.0 environment: # Remove TRANSPORT_TYPE to disable tracing - TRANSPORT_TYPE=http @@ -28,7 +16,7 @@ query: links: - mysql:storage web: - image: openzipkin/zipkin-web:1.28.0 + image: openzipkin/zipkin-web:1.30.0 environment: # Remove TRANSPORT_TYPE to disable tracing - TRANSPORT_TYPE=http diff --git a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-zipkin/pom.xml b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-zipkin/pom.xml index 580055ee0..0b69d9ac8 100644 --- a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-zipkin/pom.xml +++ b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-zipkin/pom.xml @@ -36,6 +36,14 @@ true + + org.apache.maven.plugins + maven-compiler-plugin + + 1.8 + 1.8 + + diff --git a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-zipkin/src/main/java/sample/SampleZipkinApplication.java b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-zipkin/src/main/java/sample/SampleZipkinApplication.java index 25713e633..99176d618 100644 --- a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-zipkin/src/main/java/sample/SampleZipkinApplication.java +++ b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-zipkin/src/main/java/sample/SampleZipkinApplication.java @@ -47,7 +47,7 @@ public class SampleZipkinApplication { SpringApplication.run(SampleZipkinApplication.class, args); } - // Use this for debugging (or if there is no Zipkin collector running on port 9410) + // Use this for debugging (or if there is no Zipkin server running on port 9411) @Bean @ConditionalOnProperty(value="sample.zipkin.enabled", havingValue="false") public SpanCollector spanCollector() { diff --git a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-zipkin/src/test/java/integration/ZipkinDockerTests.java b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-zipkin/src/test/java/integration/ZipkinDockerTests.java index 867fa19d7..5722b7317 100644 --- a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-zipkin/src/test/java/integration/ZipkinDockerTests.java +++ b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-zipkin/src/test/java/integration/ZipkinDockerTests.java @@ -55,16 +55,12 @@ public class ZipkinDockerTests extends AbstractIntegrationTest { public static DockerComposeContainer environment = new DockerComposeContainer(new File("src/test/resources/docker-compose.yml")) .withExposedService("rabbitmq_1", 5672) - .withExposedService("collector_1", 9410) - .withExposedService("collector_1", 9900) .withExposedService("mysql_1", 3306) - .withExposedService("query_1", 9411) - .withExposedService("query_1", 9901); + .withExposedService("query_1", 9411); @Before public void setup() { await().until(zipkinQueryServerIsUp()); - await().until(zipkinCollectorServerIsUp()); } @Test @@ -96,7 +92,6 @@ public class ZipkinDockerTests extends AbstractIntegrationTest { private 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) @@ -105,7 +100,6 @@ public class ZipkinDockerTests extends AbstractIntegrationTest { .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) @@ -122,7 +116,6 @@ public class ZipkinDockerTests extends AbstractIntegrationTest { private List annotationsNotFoundInZipkin(List spans) { String binaryAnnotationName = "random-sleep-millis"; Optional names = spans.stream() - .filter(span -> span.binaryAnnotations != null) .map(span -> span.binaryAnnotations) .flatMap(Collection::stream) .filter(span -> span.endpoint != null) diff --git a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-zipkin/src/test/resources/docker-compose.yml b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-zipkin/src/test/resources/docker-compose.yml index 22c392f76..017d1bb09 100644 --- a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-zipkin/src/test/resources/docker-compose.yml +++ b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-zipkin/src/test/resources/docker-compose.yml @@ -1,16 +1,5 @@ -collector: - image: openzipkin/zipkin-collector:1.25.0 - environment: - - TRANSPORT_TYPE=scribe - - STORAGE_TYPE=mysql - ports: - - 9410:9410 - - 9900:9900 - links: - - mysql:storage - query: - image: openzipkin/zipkin-query:1.25.0 + image: openzipkin/zipkin-query:1.30.0 environment: # Remove TRANSPORT_TYPE to disable tracing - TRANSPORT_TYPE=http @@ -28,6 +17,6 @@ rabbitmq: - 15672 mysql: - image: openzipkin/zipkin-mysql:1.25.0 + image: openzipkin/zipkin-mysql:1.30.0 ports: - - 3306:3306 \ No newline at end of file + - 3306:3306 diff --git a/spring-cloud-sleuth-zipkin-stream/pom.xml b/spring-cloud-sleuth-zipkin-stream/pom.xml index 141dfbe41..a24e82385 100644 --- a/spring-cloud-sleuth-zipkin-stream/pom.xml +++ b/spring-cloud-sleuth-zipkin-stream/pom.xml @@ -154,6 +154,14 @@ + + org.apache.maven.plugins + maven-compiler-plugin + + 1.8 + 1.8 + + diff --git a/spring-cloud-sleuth-zipkin-stream/src/main/java/org/springframework/cloud/sleuth/zipkin/stream/SamplingZipkinSpanIterator.java b/spring-cloud-sleuth-zipkin-stream/src/main/java/org/springframework/cloud/sleuth/zipkin/stream/SamplingZipkinSpanIterator.java new file mode 100644 index 000000000..8eb0821d1 --- /dev/null +++ b/spring-cloud-sleuth-zipkin-stream/src/main/java/org/springframework/cloud/sleuth/zipkin/stream/SamplingZipkinSpanIterator.java @@ -0,0 +1,78 @@ +/* + * Copyright 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.zipkin.stream; + +import io.zipkin.Sampler; +import java.util.Iterator; +import java.util.NoSuchElementException; +import lombok.extern.apachecommons.CommonsLog; +import org.springframework.cloud.sleuth.Span; +import org.springframework.cloud.sleuth.stream.Host; +import org.springframework.cloud.sleuth.stream.SleuthSink; +import org.springframework.cloud.sleuth.stream.Spans; + +/** + * This converts sleuth spans to zipkin ones, skipping invalid or unsampled. + */ +@CommonsLog +final class SamplingZipkinSpanIterator implements Iterator { + + private final Sampler sampler; + private final Iterator delegate; + private final Host host; + private io.zipkin.Span peeked; + + SamplingZipkinSpanIterator(Sampler sampler, Spans input) { + this.sampler = sampler; + this.delegate = input.getSpans().iterator(); + this.host = input.getHost(); + } + + @Override + public boolean hasNext() { + while (peeked == null && delegate.hasNext()) { + peeked = convertAndSample(delegate.next(), host); + } + return peeked != null; + } + + @Override + public io.zipkin.Span next() { + // implicitly peeks + if (!hasNext()) throw new NoSuchElementException(); + io.zipkin.Span result = peeked; + peeked = null; + return result; + } + + @Override + public void remove() { + throw new UnsupportedOperationException("remove"); + } + + /** returns a converted span or null if it is invalid or unsampled. */ + io.zipkin.Span convertAndSample(Span input, Host host) { + if (!input.getName().equals("message/" + SleuthSink.INPUT)) { + io.zipkin.Span result = ZipkinMessageListener.convert(input, host); + if (this.sampler.isSampled(result.traceId)) { + return result; + } + } else { + log.warn("Message tracing cycle detected for: " + input); + } + return null; + } +} \ No newline at end of file diff --git a/spring-cloud-sleuth-zipkin-stream/src/main/java/org/springframework/cloud/sleuth/zipkin/stream/ZipkinMessageListener.java b/spring-cloud-sleuth-zipkin-stream/src/main/java/org/springframework/cloud/sleuth/zipkin/stream/ZipkinMessageListener.java index 863905ff3..056488c6d 100644 --- a/spring-cloud-sleuth-zipkin-stream/src/main/java/org/springframework/cloud/sleuth/zipkin/stream/ZipkinMessageListener.java +++ b/spring-cloud-sleuth-zipkin-stream/src/main/java/org/springframework/cloud/sleuth/zipkin/stream/ZipkinMessageListener.java @@ -1,14 +1,15 @@ package org.springframework.cloud.sleuth.zipkin.stream; +import io.zipkin.Sampler; import java.io.UnsupportedEncodingException; -import java.util.ArrayList; import java.util.Collections; -import java.util.List; +import java.util.Iterator; import java.util.Map; import javax.sql.DataSource; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.condition.ConditionOutcome; import org.springframework.boot.autoconfigure.condition.SpringBootCondition; import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties; @@ -51,19 +52,14 @@ public class ZipkinMessageListener { @Autowired SpanStore spanStore; + @Autowired + Sampler sampler; + @ServiceActivator(inputChannel = SleuthSink.INPUT) public void sink(Spans input) { - List spans = new ArrayList<>(); - for (Span span : input.getSpans()) { - if (!span.getName().equals("message/" + SleuthSink.INPUT)) { - spans.add(convert(span, input.getHost())); - } - else { - log.warn("Message tracing cycle detected for: " + span); - } - } - if (!spans.isEmpty()) { - this.spanStore.accept(spans); + Iterator sampled = new SamplingZipkinSpanIterator(sampler, input); + if (sampled.hasNext()) { + this.spanStore.accept(sampled); } } @@ -196,6 +192,14 @@ public class ZipkinMessageListener { return new CloudFactory().getCloud(); } + @Value("${zipkin.collector.sample-rate:1.0}") + float sampleRate = 1.0f; + + @Bean + Sampler traceIdSampler() { + return Sampler.create(this.sampleRate); + } + @Bean @ConfigurationProperties(DataSourceProperties.PREFIX) public DataSource dataSource() { diff --git a/spring-cloud-sleuth-zipkin-stream/src/test/resources/application.yml b/spring-cloud-sleuth-zipkin-stream/src/test/resources/application.yml new file mode 100644 index 000000000..159f475df --- /dev/null +++ b/spring-cloud-sleuth-zipkin-stream/src/test/resources/application.yml @@ -0,0 +1,7 @@ +zipkin: + collector: + sample-rate: 1.0 # percentage to traces to retain + query: + lookback: 86400000 # 7 days in millis + store: + type: mem # default is inMemory \ No newline at end of file diff --git a/spring-cloud-sleuth-zipkin/docker-compose.yml b/spring-cloud-sleuth-zipkin/docker-compose.yml index 278e87ce8..5375fd21c 100644 --- a/spring-cloud-sleuth-zipkin/docker-compose.yml +++ b/spring-cloud-sleuth-zipkin/docker-compose.yml @@ -1,21 +1,9 @@ mysql: - image: openzipkin/zipkin-mysql:1.28.0 + image: openzipkin/zipkin-mysql:1.30.0 ports: - 3306:3306 -collector: - image: openzipkin/zipkin-collector:1.28.0 - environment: - - TRANSPORT_TYPE=scribe - - STORAGE_TYPE=mysql - expose: - - 9410 - ports: - - 9410:9410 - - 9900:9900 - links: - - mysql:storage query: - image: openzipkin/zipkin-query:1.28.0 + image: openzipkin/zipkin-query:1.30.0 environment: # Remove TRANSPORT_TYPE to disable tracing - TRANSPORT_TYPE=http @@ -28,7 +16,7 @@ query: links: - mysql:storage web: - image: openzipkin/zipkin-web:1.28.0 + image: openzipkin/zipkin-web:1.30.0 environment: # Remove TRANSPORT_TYPE to disable tracing - TRANSPORT_TYPE=http diff --git a/spring-cloud-sleuth-zipkin/pom.xml b/spring-cloud-sleuth-zipkin/pom.xml index 6029e4d97..c265f3a83 100644 --- a/spring-cloud-sleuth-zipkin/pom.xml +++ b/spring-cloud-sleuth-zipkin/pom.xml @@ -43,7 +43,7 @@ com.github.kristofa - brave-spancollector-scribe + brave-core org.projectlombok @@ -62,6 +62,10 @@ 2.1.0 test + + com.github.kristofa + brave-core + diff --git a/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin/ZipkinAutoConfiguration.java b/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin/ZipkinAutoConfiguration.java index 001abadb0..5cd7f5b85 100644 --- a/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin/ZipkinAutoConfiguration.java +++ b/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin/ZipkinAutoConfiguration.java @@ -16,6 +16,9 @@ package org.springframework.cloud.sleuth.zipkin; +import com.github.kristofa.brave.EmptySpanCollectorMetricsHandler; +import com.github.kristofa.brave.HttpSpanCollector; +import com.github.kristofa.brave.SpanCollectorMetricsHandler; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; @@ -29,24 +32,24 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import com.github.kristofa.brave.SpanCollector; -import com.github.kristofa.brave.scribe.ScribeSpanCollector; /** * @author Spencer Gibb */ @Configuration @EnableConfigurationProperties -@ConditionalOnClass(ScribeSpanCollector.class) +@ConditionalOnClass(SpanCollector.class) @ConditionalOnProperty(value = "spring.zipkin.enabled", matchIfMissing = true) public class ZipkinAutoConfiguration { @Bean @ConditionalOnMissingBean(SpanCollector.class) - public ScribeSpanCollector spanCollector() { + public SpanCollector spanCollector() { ZipkinProperties zipkin = zipkinProperties(); - ScribeSpanCollector collector = new ScribeSpanCollector(zipkin.getHost(), - zipkin.getPort(), zipkin.getCollector()); - return collector; + String url = "http://" + zipkin.getHost() + ":" + zipkin.getPort(); + // TODO: parameterize this + SpanCollectorMetricsHandler metrics = new EmptySpanCollectorMetricsHandler(); + return HttpSpanCollector.create(url, zipkin.getHttpConfig(), metrics); } @Bean diff --git a/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin/ZipkinProperties.java b/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin/ZipkinProperties.java index 5d08cd217..bac1b4a2b 100644 --- a/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin/ZipkinProperties.java +++ b/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin/ZipkinProperties.java @@ -16,10 +16,9 @@ package org.springframework.cloud.sleuth.zipkin; +import com.github.kristofa.brave.HttpSpanCollector; import org.springframework.boot.context.properties.ConfigurationProperties; -import com.github.kristofa.brave.scribe.ScribeSpanCollectorParams; - import lombok.Data; /** @@ -28,10 +27,10 @@ import lombok.Data; @ConfigurationProperties("spring.zipkin") @Data public class ZipkinProperties { - // Sample rate = 1 means every request will get traced. - private int fixedSampleRate = 1; + // Sample rate = 1.0 means 100% of requests will get traced. + private float fixedSampleRate = 1.0f; private String host = "localhost"; - private int port = 9410; + private int port = 9411; private boolean enabled = true; - private ScribeSpanCollectorParams collector = new ScribeSpanCollectorParams(); + private HttpSpanCollector.Config httpConfig = HttpSpanCollector.Config.builder().build(); }