Add Zipkin stream support
@EnableZipkinStreamServer and bind to a Spring Cloud Stream message broker. That's it. The default span store is in memory, but Zipkin also supports MySQL (and Cassandra coming soon).
This commit is contained in:
8
pom.xml
8
pom.xml
@@ -29,6 +29,7 @@
|
||||
<module>spring-cloud-sleuth-core</module>
|
||||
<module>spring-cloud-sleuth-zipkin</module>
|
||||
<module>spring-cloud-sleuth-stream</module>
|
||||
<module>spring-cloud-sleuth-zipkin-stream</module>
|
||||
<module>spring-cloud-sleuth-samples</module>
|
||||
<module>spring-cloud-starter-sleuth</module>
|
||||
<module>spring-cloud-starter-zipkin</module>
|
||||
@@ -102,6 +103,11 @@
|
||||
<artifactId>spring-cloud-sleuth-stream</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-sleuth-zipkin-stream</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-zipkin</artifactId>
|
||||
@@ -220,7 +226,7 @@
|
||||
</dependencyManagement>
|
||||
|
||||
<properties>
|
||||
<brave.version>3.1.0</brave.version>
|
||||
<brave.version>3.2.0</brave.version>
|
||||
<spring-cloud-netflix.version>1.1.0.BUILD-SNAPSHOT</spring-cloud-netflix.version>
|
||||
<aspectj.version>1.8.4</aspectj.version>
|
||||
<spock.version>1.0-groovy-2.4</spock.version>
|
||||
|
||||
41
spring-cloud-sleuth-zipkin-stream/README.md
Normal file
41
spring-cloud-sleuth-zipkin-stream/README.md
Normal file
@@ -0,0 +1,41 @@
|
||||
# Running Zipkin a Query Server
|
||||
|
||||
There are 4 parts to Zipkin: the instrumented client apps, the web UI, the backend database and the query server. The database for this implementation is MySQL.
|
||||
|
||||
> There is a running instance on PWS: http://zipkin-web.cfapps.io. It is backed by a `zipkin-java-server` with a MySQL backend and RabbitMQ (Spring Cloud Stream) for span transport.
|
||||
|
||||
## Instrumenting Apps
|
||||
|
||||
Depend on [Spring Cloud Sleuth Stream](https://github.com/spring-cloud-spring-cloud-sleuth). Bind to a rabbit service (or redis if you prefer - normal Spring Cloud Stream process).
|
||||
|
||||
## Query Server
|
||||
|
||||
Code is [here](https://github.com/spring-cloud-spring-cloud-sleuth/spring-cloud-sleuth-zipkin-stream).
|
||||
|
||||
Bind to MySQL and the same Stream service that you did in the apps (rabbit, redis, kafka). Set `spring.datasource.initialize=true` the first time you start to initialize the database. Alternatively, curl it:
|
||||
|
||||
```
|
||||
$ curl zipkin-server.cfapps.io/env -d endpoints.restart.enabled=true
|
||||
$ curl zipkin-server.cfapps.io/env -d spring.datasource.initialize=true
|
||||
$ curl zipkin-server.cfapps.io/restart -d {}
|
||||
```
|
||||
|
||||
Uses the `zipkin-server` jar from the [OSS](https://github.com/openzipkin/zipkin-java) as well as `spring-cloud-sleuth-stream`.
|
||||
|
||||
> NOTE: running in the "test" profile you don't need MySQL (the span store is in memory). You could even run in PWS without MySQL.
|
||||
|
||||
## Web UI
|
||||
|
||||
Get the jar from the [OSS](https://github.com/openzipkin/zipkin) and push it:
|
||||
|
||||
```
|
||||
$ cf push zipkin-web -p zipkin-web/build/libs/zipkin-web*all.jar
|
||||
```
|
||||
|
||||
It needs an environment variable to set the command line args:
|
||||
|
||||
```
|
||||
$ cf set-env zipkin-web JBP_CONFIG_JAVA_MAIN '{arguments: "-zipkin.web.port=:\$PORT -zipkin.web.rootUrl=/ -zipkin.web.query.dest=zipkin-server.cfapps.io:80 -zipkin.web.resourcesRoot=."}'
|
||||
```
|
||||
|
||||
NOTE: `JBP_CONFIG_JAVA_MAIN` only works with Java buildpack v3.2 and above (so not in PEZ Heritage right now).
|
||||
20
spring-cloud-sleuth-zipkin-stream/docker-compose.query.yml
Normal file
20
spring-cloud-sleuth-zipkin-stream/docker-compose.query.yml
Normal file
@@ -0,0 +1,20 @@
|
||||
query:
|
||||
image: springio/zipkin-server
|
||||
environment:
|
||||
- MYSQL_HOST=storage
|
||||
expose:
|
||||
- 9411
|
||||
ports:
|
||||
- 9411:9411
|
||||
links:
|
||||
- mysql:storage
|
||||
- rabbitmq:messages
|
||||
web:
|
||||
image: openzipkin/zipkin-web:1.25.0
|
||||
ports:
|
||||
- 8080:8080
|
||||
environment:
|
||||
- TRANSPORT_TYPE=http
|
||||
- WEB_LOG_LEVEL=DEBUG
|
||||
links:
|
||||
- query
|
||||
14
spring-cloud-sleuth-zipkin-stream/docker-compose.yml
Normal file
14
spring-cloud-sleuth-zipkin-stream/docker-compose.yml
Normal file
@@ -0,0 +1,14 @@
|
||||
mysql:
|
||||
image: mysql
|
||||
ports:
|
||||
- "3306:3306"
|
||||
environment:
|
||||
- MYSQL_ROOT_PASSWORD=root
|
||||
- MYSQL_DATABASE=test
|
||||
volumes:
|
||||
- "./conf.d:/etc/mysql/conf.d:ro"
|
||||
rabbitmq:
|
||||
image: rabbitmq:management
|
||||
ports:
|
||||
- 5672:5672
|
||||
- 15672:15672
|
||||
133
spring-cloud-sleuth-zipkin-stream/pom.xml
Normal file
133
spring-cloud-sleuth-zipkin-stream/pom.xml
Normal file
@@ -0,0 +1,133 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>spring-cloud-sleuth-zipkin-stream</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>spring-cloud-sleuth-zipkin-stream</name>
|
||||
<description>Spring Boot Zipkin Server</description>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-sleuth</artifactId>
|
||||
<version>1.0.0.BUILD-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
<docker.image.prefix>springio</docker.image.prefix>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<java.version>1.8</java.version>
|
||||
<zipkin-java.version>0.1.0</zipkin-java.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-stream-rabbit</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<artifactId>objenesis</artifactId>
|
||||
<groupId>org.objenesis</groupId>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-jdbc</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-sleuth</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-sleuth-stream</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-cloud-connectors</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.zipkin</groupId>
|
||||
<artifactId>zipkin-java-server</artifactId>
|
||||
<version>${zipkin-java.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.zipkin</groupId>
|
||||
<artifactId>zipkin-java-jdbc</artifactId>
|
||||
<version>${zipkin-java.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>mysql</groupId>
|
||||
<artifactId>mysql-connector-java</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-stream-test-support</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>objenesis</artifactId>
|
||||
<groupId>org.objenesis</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>com.spotify</groupId>
|
||||
<artifactId>docker-maven-plugin</artifactId>
|
||||
<version>0.3.5</version>
|
||||
<configuration>
|
||||
<imageName>${docker.image.prefix}/${project.artifactId}</imageName>
|
||||
<dockerDirectory>src/main/docker</dockerDirectory>
|
||||
<resources>
|
||||
<resource>
|
||||
<targetPath>/</targetPath>
|
||||
<directory>${project.build.directory}</directory>
|
||||
<include>${project.build.finalName}.jar</include>
|
||||
</resource>
|
||||
</resources>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,5 @@
|
||||
FROM frolvlad/alpine-oraclejdk8
|
||||
VOLUME /tmp
|
||||
ADD spring-cloud-sleuth-zipkin-stream-1.0.0.BUILD-SNAPSHOT.jar app.jar
|
||||
RUN sh -c 'touch /app.jar'
|
||||
CMD ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
|
||||
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* Copyright 2015 The OpenZipkin 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 java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.springframework.cloud.sleuth.stream.SleuthSink;
|
||||
import org.springframework.cloud.stream.annotation.EnableBinding;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
import io.zipkin.server.EnableZipkinServer;
|
||||
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
@EnableBinding(SleuthSink.class)
|
||||
@EnableZipkinServer
|
||||
@Import(ZipkinMessageListener.class)
|
||||
public @interface EnableZipkinStreamServer {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,223 @@
|
||||
package org.springframework.cloud.sleuth.zipkin.stream;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.apache.thrift.TException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionOutcome;
|
||||
import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
|
||||
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.cloud.Cloud;
|
||||
import org.springframework.cloud.CloudFactory;
|
||||
import org.springframework.cloud.sleuth.Span;
|
||||
import org.springframework.cloud.sleuth.TimelineAnnotation;
|
||||
import org.springframework.cloud.sleuth.stream.Host;
|
||||
import org.springframework.cloud.sleuth.stream.SleuthSink;
|
||||
import org.springframework.cloud.sleuth.stream.Spans;
|
||||
import org.springframework.cloud.sleuth.zipkin.stream.ZipkinMessageListener.NotSleuthStreamClient;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ConditionContext;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.core.env.MapPropertySource;
|
||||
import org.springframework.core.type.AnnotatedTypeMetadata;
|
||||
import org.springframework.integration.annotation.MessageEndpoint;
|
||||
import org.springframework.integration.annotation.ServiceActivator;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import io.zipkin.Annotation;
|
||||
import io.zipkin.BinaryAnnotation;
|
||||
import io.zipkin.BinaryAnnotation.Type;
|
||||
import io.zipkin.Endpoint;
|
||||
import io.zipkin.Span.Builder;
|
||||
import io.zipkin.SpanStore;
|
||||
import lombok.extern.apachecommons.CommonsLog;
|
||||
|
||||
@MessageEndpoint
|
||||
@CommonsLog
|
||||
@Conditional(NotSleuthStreamClient.class)
|
||||
public class ZipkinMessageListener {
|
||||
|
||||
@Autowired
|
||||
SpanStore spanStore;
|
||||
|
||||
@ServiceActivator(inputChannel = SleuthSink.INPUT)
|
||||
public void sink(Spans input) throws TException {
|
||||
List<io.zipkin.Span> 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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a given Sleuth span to a Zipkin Span.
|
||||
* <ul>
|
||||
* <li>Set ids, etc
|
||||
* <li>Create timeline annotations based on data from Span object.
|
||||
* <li>Create binary annotations based on data from Span object.
|
||||
* </ul>
|
||||
*/
|
||||
public io.zipkin.Span convert(Span span, Host host) {
|
||||
Builder zipkinSpan = new io.zipkin.Span.Builder();
|
||||
|
||||
Endpoint ep = Endpoint.create(host.getServiceName(), host.getIpv4(),
|
||||
host.getPort().shortValue());
|
||||
List<Annotation> annotationList = createZipkinAnnotations(span, ep);
|
||||
List<BinaryAnnotation> binaryAnnotationList = createZipkinBinaryAnnotations(span,
|
||||
ep);
|
||||
zipkinSpan.traceId(hash(span.getTraceId()));
|
||||
if (span.getParents().size() > 0) {
|
||||
if (span.getParents().size() > 1) {
|
||||
log.error("zipkin doesn't support spans with multiple parents. Omitting "
|
||||
+ "other parents for " + span);
|
||||
}
|
||||
zipkinSpan.parentId(hash(span.getParents().get(0)));
|
||||
}
|
||||
zipkinSpan.id(hash(span.getSpanId()));
|
||||
if (StringUtils.hasText(span.getName())) {
|
||||
zipkinSpan.name(span.getName());
|
||||
}
|
||||
for (Annotation annotation : annotationList) {
|
||||
zipkinSpan.addAnnotation(annotation);
|
||||
}
|
||||
for (BinaryAnnotation annotation : binaryAnnotationList) {
|
||||
zipkinSpan.addBinaryAnnotation(annotation);
|
||||
}
|
||||
return zipkinSpan.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add annotations from the sleuth Span.
|
||||
*/
|
||||
private List<Annotation> createZipkinAnnotations(Span span, Endpoint endpoint) {
|
||||
List<Annotation> annotationList = new ArrayList<>();
|
||||
for (TimelineAnnotation ta : span.getTimelineAnnotations()) {
|
||||
Annotation zipkinAnnotation = createZipkinAnnotation(ta.getMsg(),
|
||||
ta.getTime(), endpoint, true);
|
||||
annotationList.add(zipkinAnnotation);
|
||||
}
|
||||
return annotationList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a list of Annotations that are present in sleuth Span object.
|
||||
*
|
||||
* @return list of Annotations that could be added to Zipkin Span.
|
||||
*/
|
||||
private List<BinaryAnnotation> createZipkinBinaryAnnotations(Span span,
|
||||
Endpoint endpoint) {
|
||||
List<BinaryAnnotation> l = new ArrayList<>();
|
||||
for (Map.Entry<String, String> e : span.getAnnotations().entrySet()) {
|
||||
BinaryAnnotation.Builder binaryAnn = new BinaryAnnotation.Builder();
|
||||
binaryAnn.type(Type.STRING);
|
||||
binaryAnn.key(e.getKey());
|
||||
try {
|
||||
binaryAnn.value(e.getValue().getBytes("UTF-8"));
|
||||
}
|
||||
catch (UnsupportedEncodingException ex) {
|
||||
log.error("Error encoding string as UTF-8", ex);
|
||||
}
|
||||
binaryAnn.endpoint(endpoint);
|
||||
l.add(binaryAnn.build());
|
||||
}
|
||||
return l;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an annotation with the correct times and endpoint.
|
||||
*
|
||||
* @param value Annotation value
|
||||
* @param time timestamp will be extracted
|
||||
* @param endpoint the endpoint this annotation will be associated with.
|
||||
* @param sendRequest use the first or last timestamp.
|
||||
*/
|
||||
private static Annotation createZipkinAnnotation(String value, long time,
|
||||
Endpoint endpoint, boolean sendRequest) {
|
||||
Annotation.Builder annotation = new Annotation.Builder();
|
||||
annotation.endpoint(endpoint);
|
||||
|
||||
// Zipkin is in microseconds
|
||||
if (sendRequest) {
|
||||
annotation.timestamp(time * 1000);
|
||||
}
|
||||
else {
|
||||
annotation.timestamp(time * 1000);
|
||||
}
|
||||
annotation.value(value);
|
||||
return annotation.build();
|
||||
}
|
||||
|
||||
private static long hash(String string) {
|
||||
long h = 1125899906842597L;
|
||||
if (string == null) {
|
||||
return h;
|
||||
}
|
||||
int len = string.length();
|
||||
|
||||
for (int i = 0; i < len; i++) {
|
||||
h = 31 * h + string.charAt(i);
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
protected static class NotSleuthStreamClient extends SpringBootCondition {
|
||||
|
||||
@Override
|
||||
public ConditionOutcome getMatchOutcome(ConditionContext context,
|
||||
AnnotatedTypeMetadata metadata) {
|
||||
Environment environment = context.getEnvironment();
|
||||
if ("true".equals(environment
|
||||
.resolvePlaceholders("${spring.sleuth.stream.enabled:}"))) {
|
||||
return ConditionOutcome
|
||||
.noMatch("Found spring.sleuth.stream.enabled=true");
|
||||
}
|
||||
if (environment instanceof ConfigurableEnvironment) {
|
||||
ConfigurableEnvironment configurable = (ConfigurableEnvironment) environment;
|
||||
configurable.getPropertySources()
|
||||
.addLast(
|
||||
new MapPropertySource("spring.sleuth.stream",
|
||||
Collections.<String, Object>singletonMap(
|
||||
"spring.sleuth.stream.enabled",
|
||||
"false")));
|
||||
}
|
||||
return ConditionOutcome.match("Not found: spring.sleuth.stream.enabled");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@Profile("cloud")
|
||||
protected static class CloudDataSourceConfiguration {
|
||||
|
||||
@Bean
|
||||
public Cloud cloud() {
|
||||
return new CloudFactory().getCloud();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConfigurationProperties(DataSourceProperties.PREFIX)
|
||||
public DataSource dataSource() {
|
||||
return cloud().getSingletonServiceConnector(DataSource.class, null);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package org.springframework.cloud.sleuth.zipkin.stream;
|
||||
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||
|
||||
@SpringBootApplication
|
||||
@EnableZipkinStreamServer
|
||||
public class ZipkinQueryServerApplication {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
new SpringApplicationBuilder(ZipkinQueryServerApplication.class)
|
||||
.properties("spring.config.name=zipkin-server").run(args);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
server:
|
||||
port: 9411
|
||||
|
||||
spring:
|
||||
datasource:
|
||||
schema: classpath:/mysql.sql
|
||||
url: jdbc:mysql://${MYSQL_HOST:localhost}/test
|
||||
username: root
|
||||
password: root
|
||||
# Switch this on to create the schema on startup:
|
||||
initialize: false
|
||||
continueOnError: true
|
||||
sleuth:
|
||||
enabled: false
|
||||
zipkin:
|
||||
store:
|
||||
type: mysql # default is inMemory
|
||||
|
||||
---
|
||||
spring:
|
||||
profiles: test
|
||||
zipkin:
|
||||
store:
|
||||
type: mem # default is inMemory
|
||||
@@ -0,0 +1,31 @@
|
||||
package org.springframework.cloud.sleuth.zipkin.stream;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.IntegrationTest;
|
||||
import org.springframework.boot.test.SpringApplicationConfiguration;
|
||||
import org.springframework.cloud.sleuth.zipkin.stream.ZipkinQueryServerApplication;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.test.context.ActiveProfiles;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@SpringApplicationConfiguration(classes = ZipkinQueryServerApplication.class)
|
||||
@IntegrationTest({ "server.port=0", "spring.datasource.initialize=true" })
|
||||
@ActiveProfiles("test")
|
||||
public class ZipkinServerApplicationTests {
|
||||
|
||||
@Autowired
|
||||
private JdbcTemplate jdbcTemplate;
|
||||
|
||||
@Test
|
||||
public void contextLoads() {
|
||||
int count = this.jdbcTemplate.queryForObject("SELECT COUNT(*) FROM zipkin_spans",
|
||||
Integer.class);
|
||||
assertEquals(0, count);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
drop table zipkin_spans;
|
||||
drop table zipkin_annotations;
|
||||
drop table zipkin_binary_annotations;
|
||||
drop table zipkin_dependencies;
|
||||
drop table zipkin_dependency_links;
|
||||
Reference in New Issue
Block a user