Updates to latest zipkin and brave, removing Scribe dependency
Recent versions of zipkin and brave operate with http instead of scribe. This changes the implementation accordingly, as well adds a sampler to the POST endpoint. A notable impact is that we no longer require a collector process, as the zipkin server's POST endpoint is a collector.
This commit is contained in:
@@ -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).
|
* 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).
|
* 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).
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ The Ribbon sample makes an interesting demo or playground for learning about zip
|
|||||||
=== Running samples with Zipkin
|
=== 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]
|
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).
|
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)
|
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
|
=== 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).
|
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`.
|
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`.
|
||||||
|
|||||||
@@ -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).
|
* 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).
|
* 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).
|
||||||
|
|||||||
@@ -7,6 +7,18 @@
|
|||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
<name>Spring Cloud Sleuth Core</name>
|
<name>Spring Cloud Sleuth Core</name>
|
||||||
<description>Spring Cloud Sleuth Core</description>
|
<description>Spring Cloud Sleuth Core</description>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<source>1.8</source>
|
||||||
|
<target>1.8</target>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.springframework.cloud</groupId>
|
<groupId>org.springframework.cloud</groupId>
|
||||||
|
|||||||
@@ -14,10 +14,10 @@
|
|||||||
<name>spring-cloud-sleuth-dependencies</name>
|
<name>spring-cloud-sleuth-dependencies</name>
|
||||||
<description>Spring Cloud Sleuth Dependencies</description>
|
<description>Spring Cloud Sleuth Dependencies</description>
|
||||||
<properties>
|
<properties>
|
||||||
<brave.version>3.2.0</brave.version>
|
<brave.version>3.4.0</brave.version>
|
||||||
<spring-cloud-netflix.version>1.1.0.BUILD-SNAPSHOT</spring-cloud-netflix.version>
|
<spring-cloud-netflix.version>1.1.0.BUILD-SNAPSHOT</spring-cloud-netflix.version>
|
||||||
<aspectj.version>1.8.4</aspectj.version>
|
<aspectj.version>1.8.4</aspectj.version>
|
||||||
<zipkin-java.version>0.1.2</zipkin-java.version>
|
<zipkin-java.version>0.4.0</zipkin-java.version>
|
||||||
</properties>
|
</properties>
|
||||||
<dependencyManagement>
|
<dependencyManagement>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
@@ -60,7 +60,7 @@
|
|||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.github.kristofa</groupId>
|
<groupId>com.github.kristofa</groupId>
|
||||||
<artifactId>brave-spancollector-scribe</artifactId>
|
<artifactId>brave-core</artifactId>
|
||||||
<version>${brave.version}</version>
|
<version>${brave.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
@@ -73,6 +73,11 @@
|
|||||||
<artifactId>aspectjweaver</artifactId>
|
<artifactId>aspectjweaver</artifactId>
|
||||||
<version>${aspectj.version}</version>
|
<version>${aspectj.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.zipkin</groupId>
|
||||||
|
<artifactId>zipkin-java-core</artifactId>
|
||||||
|
<version>${zipkin-java.version}</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>io.zipkin</groupId>
|
<groupId>io.zipkin</groupId>
|
||||||
<artifactId>zipkin-java-server</artifactId>
|
<artifactId>zipkin-java-server</artifactId>
|
||||||
|
|||||||
@@ -36,6 +36,14 @@
|
|||||||
<skip>true</skip>
|
<skip>true</skip>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<source>1.8</source>
|
||||||
|
<target>1.8</target>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ public class SampleMessagingApplication {
|
|||||||
SpringApplication.run(SampleMessagingApplication.class, args);
|
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
|
@Bean
|
||||||
@ConditionalOnProperty(value="sample.zipkin.enabled", havingValue="false")
|
@ConditionalOnProperty(value="sample.zipkin.enabled", havingValue="false")
|
||||||
public SpanCollector spanCollector() {
|
public SpanCollector spanCollector() {
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ public class SampleRibbonApplication {
|
|||||||
SpringApplication.run(SampleRibbonApplication.class, args);
|
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
|
@Bean
|
||||||
@ConditionalOnProperty(value="sample.zipkin.enabled", havingValue="false")
|
@ConditionalOnProperty(value="sample.zipkin.enabled", havingValue="false")
|
||||||
public SpanCollector spanCollector() {
|
public SpanCollector spanCollector() {
|
||||||
|
|||||||
@@ -111,9 +111,8 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>io.zipkin</groupId>
|
<groupId>io.zipkin</groupId>
|
||||||
<artifactId>zipkin-java-core</artifactId>
|
<artifactId>zipkin-java-core</artifactId>
|
||||||
<version>0.1.1</version>
|
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
@@ -15,21 +15,26 @@
|
|||||||
*/
|
*/
|
||||||
package tools;
|
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.SpanCollector;
|
||||||
import com.github.kristofa.brave.scribe.ScribeSpanCollector;
|
import com.github.kristofa.brave.SpanCollectorMetricsHandler;
|
||||||
import com.jayway.awaitility.Awaitility;
|
import com.jayway.awaitility.Awaitility;
|
||||||
import com.jayway.awaitility.core.ConditionFactory;
|
import com.jayway.awaitility.core.ConditionFactory;
|
||||||
|
import java.net.URI;
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.cloud.sleuth.zipkin.ZipkinProperties;
|
import org.springframework.cloud.sleuth.zipkin.ZipkinProperties;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
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.util.StringUtils;
|
||||||
import org.springframework.web.client.RestTemplate;
|
import org.springframework.web.client.RestTemplate;
|
||||||
|
|
||||||
import java.net.URI;
|
|
||||||
|
|
||||||
import static java.util.concurrent.TimeUnit.SECONDS;
|
import static java.util.concurrent.TimeUnit.SECONDS;
|
||||||
import static org.assertj.core.api.BDDAssertions.then;
|
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<String> 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<String> endpointToCheckZipkinQueryHealth() {
|
protected ResponseEntity<String> endpointToCheckZipkinQueryHealth() {
|
||||||
URI uri = URI.create(getZipkinServicesQueryUrl());
|
URI uri = URI.create(getZipkinServicesQueryUrl());
|
||||||
log.info("Sending request to the Zipkin query service [{}]", uri);
|
log.info("Sending request to the Zipkin query service [{}]", uri);
|
||||||
return exchangeRequest(uri);
|
return exchangeRequest(uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ResponseEntity<String> endpointToCheckZipkinCollectorHealth() {
|
|
||||||
URI uri = URI.create(getZipkinCollectorHealthUrl());
|
|
||||||
log.info("Sending request to the Zipkin collector service [{}]", uri);
|
|
||||||
return exchangeRequest(uri);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected ResponseEntity<String> checkStateOfTheTraceId(String traceId) {
|
protected ResponseEntity<String> checkStateOfTheTraceId(String traceId) {
|
||||||
String hexTraceId = zipkinHashedHexStringTraceId(traceId);
|
String hexTraceId = zipkinHashedHexStringTraceId(traceId);
|
||||||
URI uri = URI.create(getZipkinTraceQueryUrl() + hexTraceId);
|
URI uri = URI.create(getZipkinTraceQueryUrl() + hexTraceId);
|
||||||
@@ -138,10 +125,6 @@ public abstract class AbstractIntegrationTest {
|
|||||||
return getDockerUrl() + ":9411/api/v1/services";
|
return getDockerUrl() + ":9411/api/v1/services";
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String getZipkinCollectorHealthUrl() {
|
|
||||||
return getDockerUrl() + ":9900/health";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
public static class Config {
|
public static class Config {
|
||||||
@Bean
|
@Bean
|
||||||
@@ -155,7 +138,7 @@ public abstract class AbstractIntegrationTest {
|
|||||||
public static class ZipkinConfig {
|
public static class ZipkinConfig {
|
||||||
@Bean
|
@Bean
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public ScribeSpanCollector spanCollector(final ZipkinProperties zipkin) {
|
public SpanCollector spanCollector(final ZipkinProperties zipkin) {
|
||||||
await().until(new Runnable() {
|
await().until(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
@@ -170,9 +153,11 @@ public abstract class AbstractIntegrationTest {
|
|||||||
return getSpanCollector(zipkin);
|
return getSpanCollector(zipkin);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ScribeSpanCollector getSpanCollector(ZipkinProperties zipkin) {
|
private SpanCollector getSpanCollector(ZipkinProperties zipkin) {
|
||||||
return new ScribeSpanCollector(getDockerURI().getHost(),
|
String url = "http://" + getDockerURI().getHost() + ":" + zipkin.getPort();
|
||||||
zipkin.getPort(), zipkin.getCollector());
|
// TODO: parameterize this
|
||||||
}
|
SpanCollectorMetricsHandler metrics = new EmptySpanCollectorMetricsHandler();
|
||||||
}
|
return HttpSpanCollector.create(url, zipkin.getHttpConfig(), metrics);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ zipkin:
|
|||||||
- mysql
|
- mysql
|
||||||
- rabbitmq
|
- rabbitmq
|
||||||
web:
|
web:
|
||||||
image: openzipkin/zipkin-web:1.28.0
|
image: openzipkin/zipkin-web:1.30.0
|
||||||
ports:
|
ports:
|
||||||
- 8080:8080
|
- 8080:8080
|
||||||
environment:
|
environment:
|
||||||
|
|||||||
@@ -8,6 +8,10 @@ spring:
|
|||||||
initialize: false
|
initialize: false
|
||||||
|
|
||||||
zipkin:
|
zipkin:
|
||||||
|
collector:
|
||||||
|
sample-rate: 1.0 # percentage to traces to retain
|
||||||
|
query:
|
||||||
|
lookback: 86400000 # 7 days in millis
|
||||||
store:
|
store:
|
||||||
type: mem # default is inMemory
|
type: mem # default is inMemory
|
||||||
|
|
||||||
|
|||||||
@@ -1,21 +1,9 @@
|
|||||||
mysql:
|
mysql:
|
||||||
image: openzipkin/zipkin-mysql:1.28.0
|
image: openzipkin/zipkin-mysql:1.30.0
|
||||||
ports:
|
ports:
|
||||||
- 3306:3306
|
- 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:
|
query:
|
||||||
image: openzipkin/zipkin-query:1.28.0
|
image: openzipkin/zipkin-query:1.30.0
|
||||||
environment:
|
environment:
|
||||||
# Remove TRANSPORT_TYPE to disable tracing
|
# Remove TRANSPORT_TYPE to disable tracing
|
||||||
- TRANSPORT_TYPE=http
|
- TRANSPORT_TYPE=http
|
||||||
@@ -28,7 +16,7 @@ query:
|
|||||||
links:
|
links:
|
||||||
- mysql:storage
|
- mysql:storage
|
||||||
web:
|
web:
|
||||||
image: openzipkin/zipkin-web:1.28.0
|
image: openzipkin/zipkin-web:1.30.0
|
||||||
environment:
|
environment:
|
||||||
# Remove TRANSPORT_TYPE to disable tracing
|
# Remove TRANSPORT_TYPE to disable tracing
|
||||||
- TRANSPORT_TYPE=http
|
- TRANSPORT_TYPE=http
|
||||||
|
|||||||
@@ -36,6 +36,14 @@
|
|||||||
<skip>true</skip>
|
<skip>true</skip>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<source>1.8</source>
|
||||||
|
<target>1.8</target>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ public class SampleZipkinApplication {
|
|||||||
SpringApplication.run(SampleZipkinApplication.class, args);
|
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
|
@Bean
|
||||||
@ConditionalOnProperty(value="sample.zipkin.enabled", havingValue="false")
|
@ConditionalOnProperty(value="sample.zipkin.enabled", havingValue="false")
|
||||||
public SpanCollector spanCollector() {
|
public SpanCollector spanCollector() {
|
||||||
|
|||||||
@@ -55,16 +55,12 @@ public class ZipkinDockerTests extends AbstractIntegrationTest {
|
|||||||
public static DockerComposeContainer environment =
|
public static DockerComposeContainer environment =
|
||||||
new DockerComposeContainer(new File("src/test/resources/docker-compose.yml"))
|
new DockerComposeContainer(new File("src/test/resources/docker-compose.yml"))
|
||||||
.withExposedService("rabbitmq_1", 5672)
|
.withExposedService("rabbitmq_1", 5672)
|
||||||
.withExposedService("collector_1", 9410)
|
|
||||||
.withExposedService("collector_1", 9900)
|
|
||||||
.withExposedService("mysql_1", 3306)
|
.withExposedService("mysql_1", 3306)
|
||||||
.withExposedService("query_1", 9411)
|
.withExposedService("query_1", 9411);
|
||||||
.withExposedService("query_1", 9901);
|
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setup() {
|
public void setup() {
|
||||||
await().until(zipkinQueryServerIsUp());
|
await().until(zipkinQueryServerIsUp());
|
||||||
await().until(zipkinCollectorServerIsUp());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -96,7 +92,6 @@ public class ZipkinDockerTests extends AbstractIntegrationTest {
|
|||||||
|
|
||||||
private List<String> serviceNamesNotFoundInZipkin(List<io.zipkin.Span> spans) {
|
private List<String> serviceNamesNotFoundInZipkin(List<io.zipkin.Span> spans) {
|
||||||
List<String> serviceNamesFoundInAnnotations = spans.stream()
|
List<String> serviceNamesFoundInAnnotations = spans.stream()
|
||||||
.filter(span -> span.annotations != null)
|
|
||||||
.map(span -> span.annotations)
|
.map(span -> span.annotations)
|
||||||
.flatMap(Collection::stream)
|
.flatMap(Collection::stream)
|
||||||
.filter(span -> span.endpoint != null)
|
.filter(span -> span.endpoint != null)
|
||||||
@@ -105,7 +100,6 @@ public class ZipkinDockerTests extends AbstractIntegrationTest {
|
|||||||
.distinct()
|
.distinct()
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
List<String> serviceNamesFoundInBinaryAnnotations = spans.stream()
|
List<String> serviceNamesFoundInBinaryAnnotations = spans.stream()
|
||||||
.filter(span -> span.binaryAnnotations != null)
|
|
||||||
.map(span -> span.binaryAnnotations)
|
.map(span -> span.binaryAnnotations)
|
||||||
.flatMap(Collection::stream)
|
.flatMap(Collection::stream)
|
||||||
.filter(span -> span.endpoint != null)
|
.filter(span -> span.endpoint != null)
|
||||||
@@ -122,7 +116,6 @@ public class ZipkinDockerTests extends AbstractIntegrationTest {
|
|||||||
private List<String> annotationsNotFoundInZipkin(List<io.zipkin.Span> spans) {
|
private List<String> annotationsNotFoundInZipkin(List<io.zipkin.Span> spans) {
|
||||||
String binaryAnnotationName = "random-sleep-millis";
|
String binaryAnnotationName = "random-sleep-millis";
|
||||||
Optional<String> names = spans.stream()
|
Optional<String> names = spans.stream()
|
||||||
.filter(span -> span.binaryAnnotations != null)
|
|
||||||
.map(span -> span.binaryAnnotations)
|
.map(span -> span.binaryAnnotations)
|
||||||
.flatMap(Collection::stream)
|
.flatMap(Collection::stream)
|
||||||
.filter(span -> span.endpoint != null)
|
.filter(span -> span.endpoint != null)
|
||||||
|
|||||||
@@ -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:
|
query:
|
||||||
image: openzipkin/zipkin-query:1.25.0
|
image: openzipkin/zipkin-query:1.30.0
|
||||||
environment:
|
environment:
|
||||||
# Remove TRANSPORT_TYPE to disable tracing
|
# Remove TRANSPORT_TYPE to disable tracing
|
||||||
- TRANSPORT_TYPE=http
|
- TRANSPORT_TYPE=http
|
||||||
@@ -28,6 +17,6 @@ rabbitmq:
|
|||||||
- 15672
|
- 15672
|
||||||
|
|
||||||
mysql:
|
mysql:
|
||||||
image: openzipkin/zipkin-mysql:1.25.0
|
image: openzipkin/zipkin-mysql:1.30.0
|
||||||
ports:
|
ports:
|
||||||
- 3306:3306
|
- 3306:3306
|
||||||
|
|||||||
@@ -154,6 +154,14 @@
|
|||||||
</resources>
|
</resources>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<source>1.8</source>
|
||||||
|
<target>1.8</target>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
|
|||||||
@@ -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<io.zipkin.Span> {
|
||||||
|
|
||||||
|
private final Sampler sampler;
|
||||||
|
private final Iterator<Span> 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,14 +1,15 @@
|
|||||||
package org.springframework.cloud.sleuth.zipkin.stream;
|
package org.springframework.cloud.sleuth.zipkin.stream;
|
||||||
|
|
||||||
|
import io.zipkin.Sampler;
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.Iterator;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import javax.sql.DataSource;
|
import javax.sql.DataSource;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
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.ConditionOutcome;
|
||||||
import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
|
import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
|
||||||
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
|
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
|
||||||
@@ -51,19 +52,14 @@ public class ZipkinMessageListener {
|
|||||||
@Autowired
|
@Autowired
|
||||||
SpanStore spanStore;
|
SpanStore spanStore;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
Sampler sampler;
|
||||||
|
|
||||||
@ServiceActivator(inputChannel = SleuthSink.INPUT)
|
@ServiceActivator(inputChannel = SleuthSink.INPUT)
|
||||||
public void sink(Spans input) {
|
public void sink(Spans input) {
|
||||||
List<io.zipkin.Span> spans = new ArrayList<>();
|
Iterator<io.zipkin.Span> sampled = new SamplingZipkinSpanIterator(sampler, input);
|
||||||
for (Span span : input.getSpans()) {
|
if (sampled.hasNext()) {
|
||||||
if (!span.getName().equals("message/" + SleuthSink.INPUT)) {
|
this.spanStore.accept(sampled);
|
||||||
spans.add(convert(span, input.getHost()));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
log.warn("Message tracing cycle detected for: " + span);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!spans.isEmpty()) {
|
|
||||||
this.spanStore.accept(spans);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -196,6 +192,14 @@ public class ZipkinMessageListener {
|
|||||||
return new CloudFactory().getCloud();
|
return new CloudFactory().getCloud();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Value("${zipkin.collector.sample-rate:1.0}")
|
||||||
|
float sampleRate = 1.0f;
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
Sampler traceIdSampler() {
|
||||||
|
return Sampler.create(this.sampleRate);
|
||||||
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@ConfigurationProperties(DataSourceProperties.PREFIX)
|
@ConfigurationProperties(DataSourceProperties.PREFIX)
|
||||||
public DataSource dataSource() {
|
public DataSource dataSource() {
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -1,21 +1,9 @@
|
|||||||
mysql:
|
mysql:
|
||||||
image: openzipkin/zipkin-mysql:1.28.0
|
image: openzipkin/zipkin-mysql:1.30.0
|
||||||
ports:
|
ports:
|
||||||
- 3306:3306
|
- 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:
|
query:
|
||||||
image: openzipkin/zipkin-query:1.28.0
|
image: openzipkin/zipkin-query:1.30.0
|
||||||
environment:
|
environment:
|
||||||
# Remove TRANSPORT_TYPE to disable tracing
|
# Remove TRANSPORT_TYPE to disable tracing
|
||||||
- TRANSPORT_TYPE=http
|
- TRANSPORT_TYPE=http
|
||||||
@@ -28,7 +16,7 @@ query:
|
|||||||
links:
|
links:
|
||||||
- mysql:storage
|
- mysql:storage
|
||||||
web:
|
web:
|
||||||
image: openzipkin/zipkin-web:1.28.0
|
image: openzipkin/zipkin-web:1.30.0
|
||||||
environment:
|
environment:
|
||||||
# Remove TRANSPORT_TYPE to disable tracing
|
# Remove TRANSPORT_TYPE to disable tracing
|
||||||
- TRANSPORT_TYPE=http
|
- TRANSPORT_TYPE=http
|
||||||
|
|||||||
@@ -43,7 +43,7 @@
|
|||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.github.kristofa</groupId>
|
<groupId>com.github.kristofa</groupId>
|
||||||
<artifactId>brave-spancollector-scribe</artifactId>
|
<artifactId>brave-core</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.projectlombok</groupId>
|
<groupId>org.projectlombok</groupId>
|
||||||
@@ -62,6 +62,10 @@
|
|||||||
<version>2.1.0</version>
|
<version>2.1.0</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.kristofa</groupId>
|
||||||
|
<artifactId>brave-core</artifactId>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
@@ -16,6 +16,9 @@
|
|||||||
|
|
||||||
package org.springframework.cloud.sleuth.zipkin;
|
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.Autowired;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||||
@@ -29,24 +32,24 @@ import org.springframework.context.annotation.Bean;
|
|||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
import com.github.kristofa.brave.SpanCollector;
|
import com.github.kristofa.brave.SpanCollector;
|
||||||
import com.github.kristofa.brave.scribe.ScribeSpanCollector;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Spencer Gibb
|
* @author Spencer Gibb
|
||||||
*/
|
*/
|
||||||
@Configuration
|
@Configuration
|
||||||
@EnableConfigurationProperties
|
@EnableConfigurationProperties
|
||||||
@ConditionalOnClass(ScribeSpanCollector.class)
|
@ConditionalOnClass(SpanCollector.class)
|
||||||
@ConditionalOnProperty(value = "spring.zipkin.enabled", matchIfMissing = true)
|
@ConditionalOnProperty(value = "spring.zipkin.enabled", matchIfMissing = true)
|
||||||
public class ZipkinAutoConfiguration {
|
public class ZipkinAutoConfiguration {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@ConditionalOnMissingBean(SpanCollector.class)
|
@ConditionalOnMissingBean(SpanCollector.class)
|
||||||
public ScribeSpanCollector spanCollector() {
|
public SpanCollector spanCollector() {
|
||||||
ZipkinProperties zipkin = zipkinProperties();
|
ZipkinProperties zipkin = zipkinProperties();
|
||||||
ScribeSpanCollector collector = new ScribeSpanCollector(zipkin.getHost(),
|
String url = "http://" + zipkin.getHost() + ":" + zipkin.getPort();
|
||||||
zipkin.getPort(), zipkin.getCollector());
|
// TODO: parameterize this
|
||||||
return collector;
|
SpanCollectorMetricsHandler metrics = new EmptySpanCollectorMetricsHandler();
|
||||||
|
return HttpSpanCollector.create(url, zipkin.getHttpConfig(), metrics);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
|
|||||||
@@ -16,10 +16,9 @@
|
|||||||
|
|
||||||
package org.springframework.cloud.sleuth.zipkin;
|
package org.springframework.cloud.sleuth.zipkin;
|
||||||
|
|
||||||
|
import com.github.kristofa.brave.HttpSpanCollector;
|
||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
|
||||||
import com.github.kristofa.brave.scribe.ScribeSpanCollectorParams;
|
|
||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -28,10 +27,10 @@ import lombok.Data;
|
|||||||
@ConfigurationProperties("spring.zipkin")
|
@ConfigurationProperties("spring.zipkin")
|
||||||
@Data
|
@Data
|
||||||
public class ZipkinProperties {
|
public class ZipkinProperties {
|
||||||
// Sample rate = 1 means every request will get traced.
|
// Sample rate = 1.0 means 100% of requests will get traced.
|
||||||
private int fixedSampleRate = 1;
|
private float fixedSampleRate = 1.0f;
|
||||||
private String host = "localhost";
|
private String host = "localhost";
|
||||||
private int port = 9410;
|
private int port = 9411;
|
||||||
private boolean enabled = true;
|
private boolean enabled = true;
|
||||||
private ScribeSpanCollectorParams collector = new ScribeSpanCollectorParams();
|
private HttpSpanCollector.Config httpConfig = HttpSpanCollector.Config.builder().build();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user