Trying to fix the build

This commit is contained in:
Marcin Grzejszczak
2017-11-21 19:35:17 +01:00
71 changed files with 157 additions and 2710 deletions

View File

@@ -401,7 +401,7 @@ the Spring BOM
==== Sleuth with Zipkin via HTTP
If you want both Sleuth and Zipkin just add the `spring-cloud-starter-zipkin2` dependency.
If you want both Sleuth and Zipkin just add the `spring-cloud-starter-zipkin` dependency.
[source,xml,indent=0,subs="verbatim,attributes",role="primary"]
.Maven
@@ -420,12 +420,12 @@ If you want both Sleuth and Zipkin just add the `spring-cloud-starter-zipkin2` d
<dependency> <2>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin2</artifactId>
<artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>
----
<1> In order not to pick versions by yourself it's much better if you add the dependency management via
the Spring BOM
<2> Add the dependency to `spring-cloud-starter-zipkin2`
<2> Add the dependency to `spring-cloud-starter-zipkin`
[source,groovy,indent=0,subs="verbatim,attributes",role="secondary"]
.Gradle
@@ -437,12 +437,12 @@ dependencyManagement { <1>
}
dependencies { <2>
compile "org.springframework.cloud:spring-cloud-starter-zipkin2"
compile "org.springframework.cloud:spring-cloud-starter-zipkin"
}
----
<1> In order not to pick versions by yourself it's much better if you add the dependency management via
the Spring BOM
<2> Add the dependency to `spring-cloud-starter-zipkin2`
<2> Add the dependency to `spring-cloud-starter-zipkin`
==== Sleuth with Zipkin via RabbitMQ or Kafka
@@ -451,7 +451,7 @@ dependencies. The default destination name is `zipkin`.
_Note: `spring-cloud-sleuth-stream` is deprecated and incompatible with these destinations_
If you want Sleuth over RabbitMQ add the `spring-cloud-starter-zipkin2` and `spring-rabbit`
If you want Sleuth over RabbitMQ add the `spring-cloud-starter-zipkin` and `spring-rabbit`
dependencies.
[source,xml,indent=0,subs="verbatim,attributes",role="primary"]
@@ -471,7 +471,7 @@ dependencies.
<dependency> <2>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin2</artifactId>
<artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>
<dependency> <3>
<groupId>org.springframework.amqp</groupId>
@@ -480,7 +480,7 @@ dependencies.
----
<1> In order not to pick versions by yourself it's much better if you add the dependency management via
the Spring BOM
<2> Add the dependency to `spring-cloud-starter-zipkin2` - that way all dependent dependencies will be downloaded
<2> Add the dependency to `spring-cloud-starter-zipkin` - that way all dependent dependencies will be downloaded
<3> To automatically configure rabbit, simply add the spring-rabbit dependency
[source,groovy,indent=0,subs="verbatim,attributes",role="secondary"]
@@ -493,13 +493,13 @@ dependencyManagement { <1>
}
dependencies {
compile "org.springframework.cloud:spring-cloud-starter-zipkin2" <2>
compile "org.springframework.cloud:spring-cloud-starter-zipkin" <2>
compile "org.springframework.amqp:spring-rabbit" <3>
}
----
<1> In order not to pick versions by yourself it's much better if you add the dependency management via
the Spring BOM
<2> Add the dependency to `spring-cloud-starter-zipkin2` - that way all dependent dependencies will be downloaded
<2> Add the dependency to `spring-cloud-starter-zipkin` - that way all dependent dependencies will be downloaded
<3> To automatically configure rabbit, simply add the spring-rabbit dependency
== Additional resources
@@ -553,7 +553,7 @@ a baggage element then it will be sent downstream either via HTTP or messaging t
* Provides simple metrics of accepted / dropped spans.
* If `spring-cloud-sleuth-zipkin2` then the app will generate and collect Zipkin-compatible traces.
* If `spring-cloud-sleuth-zipkin` then the app will generate and collect Zipkin-compatible traces.
By default it sends them via HTTP to a Zipkin server on localhost (port 9411).
Configure the location of the service using `spring.zipkin.baseUrl`.
- If you depend on `spring-rabbit` or `spring-kafka` your app will send traces to a broker instead of http.

View File

@@ -41,11 +41,11 @@ a baggage element then it will be sent downstream either via HTTP or messaging t
* Provides simple metrics of accepted / dropped spans.
* If `spring-cloud-sleuth-zipkin2` then the app will generate and collect Zipkin-compatible traces.
* If `spring-cloud-sleuth-zipkin` then the app will generate and collect Zipkin-compatible traces.
By default it sends them via HTTP to a Zipkin server on localhost (port 9411).
Configure the location of the service using `spring.zipkin.baseUrl`.
- If you depend on `spring-rabbit` or `spring-kafka` your app will send traces to a broker instead of http.
- Note: `spring-cloud-sleuth-stream` is deprecated and should no longer be used.
- Note: `spring-cloud-sleuth-stream` is deprecated and should no longer be used.
IMPORTANT: If using Zipkin, configure the percentage of spans exported using `spring.sleuth.sampler.percentage`
(default 0.1, i.e. 10%). *Otherwise you might think that Sleuth is not working cause it's omitting some spans.*

View File

@@ -280,7 +280,7 @@ the Spring BOM
==== Sleuth with Zipkin via HTTP
If you want both Sleuth and Zipkin just add the `spring-cloud-starter-zipkin2` dependency.
If you want both Sleuth and Zipkin just add the `spring-cloud-starter-zipkin` dependency.
[source,xml,indent=0,subs="verbatim,attributes",role="primary"]
.Maven
@@ -299,12 +299,12 @@ If you want both Sleuth and Zipkin just add the `spring-cloud-starter-zipkin2` d
<dependency> <2>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin2</artifactId>
<artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>
----
<1> In order not to pick versions by yourself it's much better if you add the dependency management via
the Spring BOM
<2> Add the dependency to `spring-cloud-starter-zipkin2`
<2> Add the dependency to `spring-cloud-starter-zipkin`
[source,groovy,indent=0,subs="verbatim,attributes",role="secondary"]
.Gradle
@@ -316,12 +316,12 @@ dependencyManagement { <1>
}
dependencies { <2>
compile "org.springframework.cloud:spring-cloud-starter-zipkin2"
compile "org.springframework.cloud:spring-cloud-starter-zipkin"
}
----
<1> In order not to pick versions by yourself it's much better if you add the dependency management via
the Spring BOM
<2> Add the dependency to `spring-cloud-starter-zipkin2`
<2> Add the dependency to `spring-cloud-starter-zipkin`
==== Sleuth with Zipkin via RabbitMQ or Kafka
@@ -330,7 +330,7 @@ dependencies. The default destination name is `zipkin`.
_Note: `spring-cloud-sleuth-stream` is deprecated and incompatible with these destinations_
If you want Sleuth over RabbitMQ add the `spring-cloud-starter-zipkin2` and `spring-rabbit`
If you want Sleuth over RabbitMQ add the `spring-cloud-starter-zipkin` and `spring-rabbit`
dependencies.
[source,xml,indent=0,subs="verbatim,attributes",role="primary"]
@@ -350,7 +350,7 @@ dependencies.
<dependency> <2>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin2</artifactId>
<artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>
<dependency> <3>
<groupId>org.springframework.amqp</groupId>
@@ -359,7 +359,7 @@ dependencies.
----
<1> In order not to pick versions by yourself it's much better if you add the dependency management via
the Spring BOM
<2> Add the dependency to `spring-cloud-starter-zipkin2` - that way all dependent dependencies will be downloaded
<2> Add the dependency to `spring-cloud-starter-zipkin` - that way all dependent dependencies will be downloaded
<3> To automatically configure rabbit, simply add the spring-rabbit dependency
[source,groovy,indent=0,subs="verbatim,attributes",role="secondary"]
@@ -372,13 +372,13 @@ dependencyManagement { <1>
}
dependencies {
compile "org.springframework.cloud:spring-cloud-starter-zipkin2" <2>
compile "org.springframework.cloud:spring-cloud-starter-zipkin" <2>
compile "org.springframework.amqp:spring-rabbit" <3>
}
----
<1> In order not to pick versions by yourself it's much better if you add the dependency management via
the Spring BOM
<2> Add the dependency to `spring-cloud-starter-zipkin2` - that way all dependent dependencies will be downloaded
<2> Add the dependency to `spring-cloud-starter-zipkin` - that way all dependent dependencies will be downloaded
<3> To automatically configure rabbit, simply add the spring-rabbit dependency
== Additional resources

View File

@@ -29,11 +29,9 @@
<module>spring-cloud-sleuth-dependencies</module>
<module>spring-cloud-sleuth-core</module>
<module>spring-cloud-sleuth-zipkin</module>
<module>spring-cloud-sleuth-zipkin2</module>
<module>spring-cloud-sleuth-stream</module>
<module>spring-cloud-starter-sleuth</module>
<module>spring-cloud-starter-zipkin</module>
<module>spring-cloud-starter-zipkin2</module>
<module>spring-cloud-sleuth-samples</module>
<module>docs</module>
</modules>

View File

@@ -16,6 +16,8 @@
package org.springframework.cloud.sleuth.instrument.web.client.feign;
import java.io.IOException;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
@@ -41,13 +43,17 @@ class TraceFeignAspect {
@Around("execution (* feign.Client.*(..)) && !within(is(FinalType))")
public Object feignClientWasCalled(final ProceedingJoinPoint pjp) throws Throwable {
Object[] args = pjp.getArgs();
Request request = (Request) args[0];
Request.Options options = (Request.Options) args[1];
Object bean = pjp.getTarget();
if (!(bean instanceof TraceFeignClient)) {
return new TraceFeignClient(this.beanFactory, (Client) bean).execute(request, options);
if (!(bean instanceof TraceFeignClient) && !(bean instanceof TraceLoadBalancerFeignClient)) {
return executeTraceFeignClient(bean, pjp);
}
return pjp.proceed();
}
Object executeTraceFeignClient(Object bean, ProceedingJoinPoint pjp) throws IOException {
Object[] args = pjp.getArgs();
Request request = (Request) args[0];
Request.Options options = (Request.Options) args[1];
return new TraceFeignClient(this.beanFactory, (Client) bean).execute(request, options);
}
}

View File

@@ -0,0 +1,77 @@
package org.springframework.cloud.sleuth.instrument.web.client.feign;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.HashMap;
import feign.Client;
import feign.Request;
import org.aspectj.lang.ProceedingJoinPoint;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.beans.factory.BeanFactory;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
/**
* @author Marcin Grzejszczak
*/
@RunWith(MockitoJUnitRunner.class)
public class TraceFeignAspectTests {
@Mock BeanFactory beanFactory;
@Mock Client client;
@Mock ProceedingJoinPoint pjp;
@Mock TraceLoadBalancerFeignClient traceLoadBalancerFeignClient;
TraceFeignAspect traceFeignAspect;
@Before
public void setup() {
stubPjp();
this.traceFeignAspect = new TraceFeignAspect(this.beanFactory) {
@Override Object executeTraceFeignClient(Object bean, ProceedingJoinPoint pjp) throws IOException {
return null;
}
};
}
private void stubPjp() {
Request request = Request.create("foo", "bar", new HashMap<>(), new byte[] {}, Charset
.defaultCharset());
Request.Options options = new Request.Options();
given(this.pjp.getArgs()).willReturn(new Object[] {request, options} );
}
@Test
public void should_wrap_feign_client_in_trace_representation() throws Throwable {
given(this.pjp.getTarget()).willReturn(this.client);
this.traceFeignAspect.feignClientWasCalled(this.pjp);
verify(this.pjp, never()).proceed();
}
@Test
public void should_not_wrap_traced_feign_client_in_trace_representation() throws Throwable {
given(this.pjp.getTarget()).willReturn(new TraceFeignClient(this.beanFactory, this.client));
this.traceFeignAspect.feignClientWasCalled(this.pjp);
verify(this.pjp).proceed();
}
@Test
public void should_not_wrap_traced_load_balancer_feign_client_in_trace_representation() throws Throwable {
given(this.pjp.getTarget()).willReturn(this.traceLoadBalancerFeignClient);
this.traceFeignAspect.feignClientWasCalled(this.pjp);
verify(this.pjp).proceed();
}
}

View File

@@ -25,21 +25,11 @@
<artifactId>spring-cloud-sleuth-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-reactor</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-zipkin</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-zipkin2</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-stream</artifactId>
@@ -55,11 +45,6 @@
<artifactId>spring-cloud-starter-zipkin</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin2</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>

View File

@@ -6,7 +6,7 @@ There are a few samples with slightly different features. You can run all of the
* `spring-cloud-sleuth-sample`: vanilla (no zipkin) web app that calls back to itself on various endpoints ("/", "/call", "/async")
* `spring-cloud-sleuth-sample-zipkin2`: same as vanilla sample but with zipkin (set `sample.zipkin.enabled=true` if you have a collector running)
* `spring-cloud-sleuth-sample-zipkin`: same as vanilla sample but with zipkin (set `sample.zipkin.enabled=true` if you have a collector running)
* `spring-cloud-sleuth-sample-messaging`: a Spring Integration application with two HTTP endpoints ("/" and "/xform")
@@ -16,7 +16,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] Server, 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-zipkin2[Spring Cloud Sleuth], or in https://github.com/openzipkin/docker-zipkin[Docker Zipkin]
1. Optionally run the https://github.com/openzipkin/zipkin[Zipkin] Server, 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 9411 to localhost, or change the `spring.zipkin.baseUrl`.
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. Go to `http://localhost:9411` for Zipkin's UI (if you are using boot2docker the host will be different)

View File

@@ -23,7 +23,7 @@
<module>spring-cloud-sleuth-sample-websocket</module>
<module>spring-cloud-sleuth-sample-feign</module>
<module>spring-cloud-sleuth-sample-ribbon</module>
<module>spring-cloud-sleuth-sample-zipkin2</module>
<module>spring-cloud-sleuth-sample-zipkin</module>
</modules>
<build>
@@ -55,10 +55,15 @@
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>io.zipkin.zipkin2</groupId>
<groupId>io.zipkin.java</groupId>
<artifactId>zipkin</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>io.zipkin.java</groupId>
<artifactId>zipkin-server</artifactId>
<version>2.2.2</version>
</dependency>
</dependencies>
</dependencyManagement>

View File

@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- ~ Copyright 2013-2017 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
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. -->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
@@ -68,7 +68,7 @@
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-zipkin2</artifactId>
<artifactId>spring-cloud-sleuth-zipkin</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>

View File

@@ -82,7 +82,7 @@
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-zipkin2</artifactId>
<artifactId>spring-cloud-sleuth-zipkin</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>

View File

@@ -70,7 +70,7 @@
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-zipkin2</artifactId>
<artifactId>spring-cloud-sleuth-zipkin</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>

View File

@@ -82,7 +82,7 @@
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-zipkin2</artifactId>
<artifactId>spring-cloud-sleuth-zipkin</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>

View File

@@ -19,10 +19,10 @@
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-sample-zipkin2</artifactId>
<artifactId>spring-cloud-sleuth-sample-zipkin</artifactId>
<packaging>jar</packaging>
<name>spring-cloud-sleuth-sample-zipkin2</name>
<description>Spring Cloud Sleuth Sample Zipkin v2</description>
<name>spring-cloud-sleuth-sample-zipkin</name>
<description>Spring Cloud Sleuth Sample Zipkin</description>
<parent>
<groupId>org.springframework.cloud</groupId>
@@ -77,7 +77,7 @@
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-zipkin2</artifactId>
<artifactId>spring-cloud-sleuth-zipkin</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>

View File

@@ -75,18 +75,32 @@
<artifactId>micrometer-core</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>io.zipkin.java</groupId>
<artifactId>zipkin</artifactId>
</dependency>
<dependency>
<groupId>io.zipkin.zipkin2</groupId>
<artifactId>zipkin</artifactId>
</dependency>
<dependency>
<groupId>io.zipkin.reporter</groupId>
<groupId>io.zipkin.reporter2</groupId>
<artifactId>zipkin-reporter</artifactId>
</dependency>
<dependency>
<groupId>io.zipkin.reporter2</groupId>
<artifactId>zipkin-sender-kafka11</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>io.zipkin.reporter2</groupId>
<artifactId>zipkin-sender-amqp-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.amqp</groupId>
<artifactId>spring-rabbit</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-messaging</artifactId>
@@ -115,7 +129,7 @@
<!-- otherwise spring boot's version of okhttp kicks zipkin-junit's deps out of alignment -->
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<artifactId>mockwebserver</artifactId>
<version>3.9.0</version>
<scope>test</scope>
</dependency>

View File

@@ -1,64 +0,0 @@
/*
* Copyright 2013-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;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.zip.GZIPOutputStream;
import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.web.client.RestTemplate;
/**
* Default {@link ZipkinRestTemplateCustomizer} that provides the GZip compression if
* {@link ZipkinProperties#compression} is enabled.
*
* @author Marcin Grzejszczak
*
* @since 1.1.0
*/
public class DefaultZipkinRestTemplateCustomizer implements ZipkinRestTemplateCustomizer {
private final ZipkinProperties zipkinProperties;
public DefaultZipkinRestTemplateCustomizer(
ZipkinProperties zipkinProperties) {
this.zipkinProperties = zipkinProperties;
}
@Override
public void customize(RestTemplate restTemplate) {
if (this.zipkinProperties.getCompression().isEnabled()) {
restTemplate.getInterceptors().add(0, new GZipInterceptor());
}
}
private class GZipInterceptor implements ClientHttpRequestInterceptor {
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws
IOException {
request.getHeaders().add("Content-Encoding", "gzip");
ByteArrayOutputStream gzipped = new ByteArrayOutputStream();
try (GZIPOutputStream compressor = new GZIPOutputStream(gzipped)) {
compressor.write(body);
}
return execution.execute(request, gzipped.toByteArray());
}
}
}

View File

@@ -1,33 +0,0 @@
/*
* Copyright 2015 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;
import zipkin.Endpoint;
/**
* Strategy for locating a zipkin {@linkplain Endpoint} for the current process.
*
* @author Dave Syer
* @since 1.0.0
* @deprecated Please use spring-cloud-sleuth-zipkin2 to report spans to Zipkin
*/
@Deprecated
public interface EndpointLocator {
Endpoint local();
}

View File

@@ -1,42 +0,0 @@
package org.springframework.cloud.sleuth.zipkin;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import zipkin.Endpoint;
/**
* Endpoint locator that will try to call an endpoint via Discovery Client
* and will fallback to Server Properties if an exception is thrown
*
* @since 1.0.0
*/
public class FallbackHavingEndpointLocator implements EndpointLocator {
private static final Log log = LogFactory.getLog(FallbackHavingEndpointLocator.class);
private final ServiceInstanceEndpointLocator serviceInstanceEndpointLocator;
private final ServerPropertiesEndpointLocator serverPropertiesEndpointLocator;
public FallbackHavingEndpointLocator(ServiceInstanceEndpointLocator serviceInstanceEndpointLocator,
ServerPropertiesEndpointLocator serverPropertiesEndpointLocator) {
this.serviceInstanceEndpointLocator = serviceInstanceEndpointLocator;
this.serverPropertiesEndpointLocator = serverPropertiesEndpointLocator;
}
@Override
public Endpoint local() {
return endpoint();
}
private Endpoint endpoint() {
if (this.serviceInstanceEndpointLocator == null) {
return this.serverPropertiesEndpointLocator.local();
}
try {
return this.serviceInstanceEndpointLocator.local();
} catch (Exception e) {
log.warn("Exception occurred while trying to fetch the Zipkin process endpoint. Falling back to server properties endpoint locator.", e);
return this.serverPropertiesEndpointLocator.local();
}
}
}

View File

@@ -1,78 +0,0 @@
package org.springframework.cloud.sleuth.zipkin;
import java.io.Closeable;
import java.io.Flushable;
import java.util.concurrent.TimeUnit;
import org.springframework.cloud.sleuth.metric.SpanMetricReporter;
import org.springframework.web.client.RestTemplate;
import zipkin.Span;
import zipkin.reporter.AsyncReporter;
import zipkin.reporter.Encoding;
/**
* Submits spans using Zipkin's {@code POST /spans} endpoint.
*
* @author Adrian Cole
* @since 1.0.0
*/
public final class HttpZipkinSpanReporter implements ZipkinSpanReporter, Flushable, Closeable {
private final RestTemplateSender sender;
private final AsyncReporter<Span> delegate;
/**
* @param restTemplate {@link RestTemplate} used for sending requests to Zipkin
* @param baseUrl URL of the zipkin query server instance. Like: http://localhost:9411/
* @param flushInterval in seconds. 0 implies spans are {@link #flush() flushed} externally.
* @param spanMetricReporter service to count number of accepted / dropped spans
*/
public HttpZipkinSpanReporter(RestTemplate restTemplate, String baseUrl, int flushInterval,
SpanMetricReporter spanMetricReporter) {
this(restTemplate, baseUrl, flushInterval, spanMetricReporter, Encoding.JSON);
}
/**
* @param restTemplate {@link RestTemplate} used for sending requests to Zipkin
* @param baseUrl URL of the zipkin query server instance. Like: http://localhost:9411/
* @param flushInterval in seconds. 0 implies spans are {@link #flush() flushed} externally.
* @param spanMetricReporter service to count number of accepted / dropped spans
* @param encoding span encoding.
*/
public HttpZipkinSpanReporter(RestTemplate restTemplate, String baseUrl, int flushInterval,
SpanMetricReporter spanMetricReporter, Encoding encoding) {
this.sender = new RestTemplateSender(restTemplate, baseUrl, encoding);
this.delegate = AsyncReporter.builder(this.sender)
.queuedMaxSpans(1000) // historical constraint. Note: AsyncReporter supports memory bounds
.messageTimeout(flushInterval, TimeUnit.SECONDS)
.metrics(new ReporterMetricsAdapter(spanMetricReporter))
.build();
}
/**
* Queues the span for collection, or drops it if the queue is full.
*
* @param span Span, should not be <code>null</code>.
*/
@Override
public void report(Span span) {
this.delegate.report(span);
}
/**
* Calling this will flush any pending spans to the http transport on the current thread.
*/
@Override
public void flush() {
this.delegate.flush();
}
/**
* Blocks until in-flight spans are sent and drops any that are left pending.
*/
@Override
public void close() {
this.delegate.close();
this.sender.close();
}
}

View File

@@ -1,31 +0,0 @@
package org.springframework.cloud.sleuth.zipkin;
import java.net.URI;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
class LoadBalancerClientZipkinLoadBalancer implements ZipkinLoadBalancer {
private final LoadBalancerClient loadBalancerClient;
private final ZipkinProperties zipkinProperties;
LoadBalancerClientZipkinLoadBalancer(LoadBalancerClient loadBalancerClient,
ZipkinProperties zipkinProperties) {
this.loadBalancerClient = loadBalancerClient;
this.zipkinProperties = zipkinProperties;
}
@Override
public URI instance() {
if (this.loadBalancerClient != null) {
URI uri = URI.create(this.zipkinProperties.getBaseUrl());
String host = uri.getHost();
ServiceInstance instance = this.loadBalancerClient.choose(host);
if (instance != null) {
return URI.create(String.format("http://%s:%s", instance.getHost(), instance.getPort()));
}
}
return URI.create(this.zipkinProperties.getBaseUrl());
}
}

View File

@@ -1,47 +0,0 @@
package org.springframework.cloud.sleuth.zipkin;
import org.springframework.cloud.sleuth.metric.SpanMetricReporter;
import zipkin.reporter.ReporterMetrics;
final class ReporterMetricsAdapter implements ReporterMetrics {
private final SpanMetricReporter spanMetricReporter;
public ReporterMetricsAdapter(SpanMetricReporter spanMetricReporter) {
this.spanMetricReporter = spanMetricReporter;
}
@Override
public void incrementMessages() {
}
@Override
public void incrementMessagesDropped(Throwable throwable) {
}
@Override
public void incrementSpans(int i) {
this.spanMetricReporter.incrementAcceptedSpans(i);
}
@Override
public void incrementSpanBytes(int i) {
}
@Override
public void incrementMessageBytes(int i) {
}
@Override
public void incrementSpansDropped(int i) {
this.spanMetricReporter.incrementDroppedSpans(i);
}
@Override
public void updateQueuedSpans(int i) {
}
@Override
public void updateQueuedBytes(int i) {
}
}

View File

@@ -1,92 +0,0 @@
package org.springframework.cloud.sleuth.zipkin;
import java.net.URI;
import java.util.List;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.RequestEntity;
import org.springframework.web.client.RestTemplate;
import zipkin.reporter.BytesMessageEncoder;
import zipkin.reporter.Callback;
import zipkin.reporter.Encoding;
import zipkin.reporter.Sender;
final class RestTemplateSender implements Sender {
final RestTemplate restTemplate;
final String url;
final Encoding encoding;
final MediaType mediaType;
RestTemplateSender(RestTemplate restTemplate, String baseUrl, Encoding encoding) {
this.restTemplate = restTemplate;
this.url = baseUrl + (baseUrl.endsWith("/") ? "" : "/") + "api/v1/spans";
this.encoding = encoding;
this.mediaType = mediaType(encoding);
}
@Override public Encoding encoding() {
return this.encoding;
}
@Override public int messageMaxBytes() {
// This will drop a span larger than 5MiB. Note: values like 512KiB benchmark better.
return 5 * 1024 * 1024;
}
@Override public int messageSizeInBytes(List<byte[]> spans) {
return encoding().listSizeInBytes(spans);
}
/** close is typically called from a different thread */
transient boolean closeCalled;
@Override public void sendSpans(List<byte[]> encodedSpans, Callback callback) {
if (this.closeCalled) throw new IllegalStateException("close");
try {
byte[] message = BytesMessageEncoder.forEncoding(this.encoding).encode(encodedSpans);
post(message);
callback.onComplete();
} catch (Throwable e) {
callback.onError(e);
if (e instanceof Error) throw (Error) e;
}
}
/** Sends an empty json message to the configured endpoint. */
@Override public CheckResult check() {
try {
post(new byte[] {'[', ']'});
return CheckResult.OK;
} catch (Exception e) {
return CheckResult.failed(e);
}
}
@Override public void close() {
this.closeCalled = true;
}
void post(byte[] json) {
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(this.mediaType);
RequestEntity<byte[]> requestEntity =
new RequestEntity<>(json, httpHeaders, HttpMethod.POST, URI.create(this.url));
this.restTemplate.exchange(requestEntity, String.class);
}
private MediaType mediaType(Encoding encoding) {
MediaType mediaType = null;
switch (this.encoding) {
case JSON:
mediaType = MediaType.APPLICATION_JSON;
break;
case THRIFT:
mediaType = new MediaType("application","x-thrift");
}
return mediaType;
}
}

View File

@@ -1,110 +0,0 @@
/*
* Copyright 2015 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;
import java.lang.invoke.MethodHandles;
import java.nio.ByteBuffer;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.web.servlet.context.ServletWebServerInitializedEvent;
import org.springframework.cloud.commons.util.InetUtils;
import org.springframework.context.event.EventListener;
import org.springframework.core.env.Environment;
import org.springframework.util.StringUtils;
import zipkin.Endpoint;
/**
* {@link EndpointLocator} implementation that:
*
* <ul>
* <li><b>address</b> - from {@link ServerProperties}</li>
* <li><b>port</b> - from lazily assigned port or {@link ServerProperties}</li>
* </ul>
*
* You can override the name using {@link ZipkinProperties.Service#setName(String)}
*
* @author Dave Syer
* @since 1.0.0
*/
public class ServerPropertiesEndpointLocator implements EndpointLocator {
private static final Log log = LogFactory.getLog(MethodHandles.lookup().lookupClass());
private static final String IP_ADDRESS_PROP_NAME = "spring.cloud.client.ipAddress";
private final ServerProperties serverProperties;
private final ZipkinProperties zipkinProperties;
private final Environment environment;
private Integer port;
public ServerPropertiesEndpointLocator(ServerProperties serverProperties,
Environment environment, ZipkinProperties zipkinProperties) {
this.serverProperties = serverProperties;
this.environment = environment;
this.zipkinProperties = zipkinProperties;
}
@Override
public Endpoint local() {
String serviceName = serviceName();
if (log.isDebugEnabled()) {
log.debug("Span will contain serviceName [" + serviceName + "]");
}
return Endpoint.builder()
.serviceName(serviceName)
.ipv4(getAddress())
.port(getPort())
.build();
}
private String serviceName() {
if (StringUtils.hasText(this.zipkinProperties.getService().getName())) {
return this.zipkinProperties.getService().getName();
}
return this.environment.getProperty("spring.application.name", "unknown");
}
@EventListener(ServletWebServerInitializedEvent.class)
public void onApplicationEvent(ServletWebServerInitializedEvent event) {
this.port = event.getSource().getPort();
}
private Integer getPort() {
if (this.port!=null) {
return this.port;
}
Integer port;
if (this.serverProperties!=null && this.serverProperties.getPort() != null && this.serverProperties.getPort() > 0) {
port = this.serverProperties.getPort();
}
else {
port = 8080;
}
return port;
}
private int getAddress() {
if (this.serverProperties != null && this.serverProperties.getAddress() != null) {
return ByteBuffer.wrap(this.serverProperties.getAddress().getAddress())
.getInt();
}
String ipAddress = this.environment
.getProperty(IP_ADDRESS_PROP_NAME, String.class);
return InetUtils.getIpAddressAsInt(ipAddress);
}
}

View File

@@ -1,77 +0,0 @@
/*
* Copyright 2015 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;
import java.lang.invoke.MethodHandles;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.commons.util.InetUtils;
import org.springframework.util.StringUtils;
import zipkin.Endpoint;
/**
* An {@link EndpointLocator} that tries to find local service information from a
* {@link org.springframework.cloud.client.serviceregistry.Registration}.
*
* You can override the name using {@link ZipkinProperties.Service#setName(String)}
*
* @author Dave Syer
* @since 1.0.0
*/
public class ServiceInstanceEndpointLocator implements EndpointLocator {
private static final Log log = LogFactory.getLog(MethodHandles.lookup().lookupClass());
private final ServiceInstance localServiceInstance;
private final ZipkinProperties zipkinProperties;
public ServiceInstanceEndpointLocator(ServiceInstance localServiceInstance,
ZipkinProperties zipkinProperties) {
this.localServiceInstance = localServiceInstance;
this.zipkinProperties = zipkinProperties;
}
@Override
public Endpoint local() {
if (this.localServiceInstance == null) {
throw new NoServiceInstanceAvailableException();
}
String serviceName = StringUtils.hasText(this.zipkinProperties.getService().getName()) ?
this.zipkinProperties.getService().getName() : this.localServiceInstance.getServiceId();
if (log.isDebugEnabled()) {
log.debug("Span will contain serviceName [" + serviceName + "]");
}
return Endpoint.builder()
.serviceName(serviceName)
.ipv4(getIpAddress(this.localServiceInstance))
.port(this.localServiceInstance.getPort()).build();
}
private int getIpAddress(ServiceInstance instance) {
try {
return InetUtils.getIpAddressAsInt(instance.getHost());
}
catch (Exception e) {
return 0;
}
}
static class NoServiceInstanceAvailableException extends RuntimeException { }
}

View File

@@ -1,269 +0,0 @@
/*
* Copyright 2013-2017 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;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.cloud.client.serviceregistry.Registration;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.cloud.sleuth.Sampler;
import org.springframework.cloud.sleuth.SpanAdjuster;
import org.springframework.cloud.sleuth.SpanReporter;
import org.springframework.cloud.sleuth.autoconfig.TraceAutoConfiguration;
import org.springframework.cloud.sleuth.metric.SpanMetricReporter;
import org.springframework.cloud.sleuth.sampler.PercentageBasedSampler;
import org.springframework.cloud.sleuth.sampler.SamplerProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.http.HttpMethod;
import org.springframework.web.client.RequestCallback;
import org.springframework.web.client.ResponseExtractor;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;
/**
* {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration Auto-configuration}
* enables reporting to Zipkin via HTTP. Has a default {@link Sampler} set as
* {@link PercentageBasedSampler}.
*
* The {@link ZipkinRestTemplateCustomizer} allows you to customize the {@link RestTemplate}
* that is used to send Spans to Zipkin. Its default implementation - {@link DefaultZipkinRestTemplateCustomizer}
* adds the GZip compression.
*
* @author Spencer Gibb
* @since 1.0.0
*
* @see PercentageBasedSampler
* @see ZipkinRestTemplateCustomizer
* @see DefaultZipkinRestTemplateCustomizer
*/
@Configuration
@EnableConfigurationProperties({ZipkinProperties.class, SamplerProperties.class})
@ConditionalOnProperty(value = "spring.zipkin.enabled", matchIfMissing = true)
@AutoConfigureBefore(TraceAutoConfiguration.class)
public class ZipkinAutoConfiguration {
@Autowired(required = false) List<SpanAdjuster> spanAdjusters = new ArrayList<>();
@Autowired ZipkinUrlExtractor extractor;
@Bean
@ConditionalOnMissingBean
public ZipkinSpanReporter reporter(SpanMetricReporter spanMetricReporter, ZipkinProperties zipkin,
ZipkinRestTemplateCustomizer zipkinRestTemplateCustomizer) {
RestTemplate restTemplate = zipkinRestTemplate(zipkin);
zipkinRestTemplateCustomizer.customize(restTemplate);
return new HttpZipkinSpanReporter(restTemplate, zipkin.getBaseUrl(), zipkin.getFlushInterval(),
spanMetricReporter, zipkin.getEncoding());
}
private RestTemplate zipkinRestTemplate(ZipkinProperties zipkinProperties) {
return new ZipkinRestTemplateWrapper(zipkinProperties, this.extractor);
}
@Configuration
@ConditionalOnClass(LoadBalancerClient.class)
static class DiscoveryClientZipkinUrlExtractorConfiguration {
@Autowired(required = false) LoadBalancerClient client;
@Bean
@ConditionalOnMissingBean
ZipkinLoadBalancer loadBalancerClientZipkinLoadBalancer(ZipkinProperties zipkinProperties) {
return new LoadBalancerClientZipkinLoadBalancer(this.client, zipkinProperties);
}
}
@Configuration
@ConditionalOnMissingClass("org.springframework.cloud.client.loadbalancer.LoadBalancerClient")
static class DefaultZipkinUrlExtractorConfiguration {
@Bean
@ConditionalOnMissingBean
ZipkinLoadBalancer loadBalancerClientZipkinLoadBalancer(final ZipkinProperties zipkinProperties) {
return new ZipkinLoadBalancer() {
@Override public URI instance() {
return URI.create(zipkinProperties.getBaseUrl());
}
};
}
}
@Bean
ZipkinUrlExtractor zipkinUrlExtractor(final ZipkinLoadBalancer zipkinLoadBalancer) {
return new ZipkinUrlExtractor() {
@Override
public URI zipkinUrl(ZipkinProperties zipkinProperties) {
return zipkinLoadBalancer.instance();
}
};
}
@Bean
@ConditionalOnMissingBean
public ZipkinRestTemplateCustomizer zipkinRestTemplateCustomizer(ZipkinProperties zipkinProperties) {
return new DefaultZipkinRestTemplateCustomizer(zipkinProperties);
}
@Configuration
@ConditionalOnClass(RefreshScope.class)
protected static class RefreshScopedPercentageBasedSamplerConfiguration {
@Bean
@RefreshScope
@ConditionalOnMissingBean
public Sampler defaultTraceSampler(SamplerProperties config) {
return new PercentageBasedSampler(config);
}
}
@Configuration
@ConditionalOnMissingClass("org.springframework.cloud.context.config.annotation.RefreshScope")
protected static class NonRefreshScopePercentageBasedSamplerConfiguration {
@Bean
@ConditionalOnMissingBean
public Sampler defaultTraceSampler(SamplerProperties config) {
return new PercentageBasedSampler(config);
}
}
@Bean
public SpanReporter zipkinSpanListener(ZipkinSpanReporter reporter, EndpointLocator endpointLocator,
Environment environment) {
return new ZipkinSpanListener(reporter, endpointLocator, environment, this.spanAdjusters);
}
@Configuration
@ConditionalOnMissingBean(EndpointLocator.class)
@ConditionalOnProperty(value = "spring.zipkin.locator.discovery.enabled", havingValue = "false", matchIfMissing = true)
protected static class DefaultEndpointLocatorConfiguration {
@Autowired(required=false)
private ServerProperties serverProperties;
@Autowired
private ZipkinProperties zipkinProperties;
@Autowired
private Environment environment;
@Bean
public EndpointLocator zipkinEndpointLocator() {
return new ServerPropertiesEndpointLocator(this.serverProperties, this.environment,
this.zipkinProperties);
}
}
@Configuration
@ConditionalOnClass(DiscoveryClient.class)
@ConditionalOnMissingBean(EndpointLocator.class)
@ConditionalOnProperty(value = "spring.zipkin.locator.discovery.enabled", havingValue = "true")
protected static class DiscoveryClientEndpointLocatorConfiguration {
@Autowired(required=false)
private ServerProperties serverProperties;
@Autowired
private ZipkinProperties zipkinProperties;
@Autowired
private Environment environment;
@Autowired(required=false)
private Registration registration;
@Bean
public EndpointLocator zipkinEndpointLocator() {
return new FallbackHavingEndpointLocator(discoveryClientEndpointLocator(),
new ServerPropertiesEndpointLocator(this.serverProperties, this.environment,
this.zipkinProperties));
}
private ServiceInstanceEndpointLocator discoveryClientEndpointLocator() {
if (this.registration != null) {
return new ServiceInstanceEndpointLocator(this.registration, this.zipkinProperties);
}
return null;
}
}
}
/**
* Internal interface to provide a way to retrieve Zipkin URI. If there's no discovery client
* then this value will be taken from the properties. Otherwise host will be assumed to
* be a service id.
*/
interface ZipkinUrlExtractor {
URI zipkinUrl(ZipkinProperties zipkinProperties);
}
/**
* Resolves at runtime where the Zipkin server is. If there's no discovery client then
* {@link URI} from the properties is taken. Otherwise service discovery is pinged
* for current Zipkin address.
*/
class ZipkinRestTemplateWrapper extends RestTemplate {
private static final Log log = LogFactory.getLog(ZipkinRestTemplateWrapper.class);
private final ZipkinProperties zipkinProperties;
private final ZipkinUrlExtractor extractor;
ZipkinRestTemplateWrapper(ZipkinProperties zipkinProperties,
ZipkinUrlExtractor extractor) {
this.zipkinProperties = zipkinProperties;
this.extractor = extractor;
}
@Override protected <T> T doExecute(URI originalUrl, HttpMethod method,
RequestCallback requestCallback,
ResponseExtractor<T> responseExtractor) throws RestClientException {
URI uri = this.extractor.zipkinUrl(this.zipkinProperties);
URI newUri = resolvedZipkinUri(originalUrl, uri);
return super.doExecute(newUri, method, requestCallback, responseExtractor);
}
private URI resolvedZipkinUri(URI originalUrl, URI resolvedZipkinUri) {
try {
return new URI(resolvedZipkinUri.getScheme(), resolvedZipkinUri.getUserInfo(),
resolvedZipkinUri.getHost(), resolvedZipkinUri.getPort(), originalUrl.getPath(),
originalUrl.getQuery(), originalUrl.getFragment());
} catch (URISyntaxException e) {
if (log.isDebugEnabled()) {
log.debug("Failed to create the new URI from original [" + originalUrl + "] and new one [" + resolvedZipkinUri + "]");
}
return originalUrl;
}
}
}

View File

@@ -1,21 +0,0 @@
package org.springframework.cloud.sleuth.zipkin;
import java.net.URI;
/**
* Load balancing strategy for picking a Zipkin instance
*
* @author Marcin Grzejszczak
* @since 1.3.0
* @deprecated Please use spring-cloud-sleuth-zipkin2 to report spans to Zipkin
*/
@Deprecated
public interface ZipkinLoadBalancer {
/**
* Returns a concrete {@link URI} of a Zipkin instance.
*
* @return {@link URI} of the picked instance
*/
URI instance();
}

View File

@@ -1,173 +0,0 @@
/*
* Copyright 2013-2015 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;
import org.springframework.boot.context.properties.ConfigurationProperties;
import zipkin.reporter.Encoding;
/**
* Zipkin settings
*
* @author Spencer Gibb
* @since 1.0.0
*/
@ConfigurationProperties("spring.zipkin")
public class ZipkinProperties {
/** URL of the zipkin query server instance. You can also provide
* the service id of the Zipkin server if Zipkin's registered in
* service discovery (e.g. http://zipkinserver/)
*/
private String baseUrl = "http://localhost:9411/";
/**
* Enables sending spans to Zipkin
*/
private boolean enabled = true;
/**
* Interval in seconds in which spans will be sent in batches to Zipkin
*/
private int flushInterval = 1;
/**
* Encoding type of spans sent to Zipkin
*/
private Encoding encoding = Encoding.JSON;
/**
* Configuration related to compressions of spans sent to Zipkin
*/
private Compression compression = new Compression();
private Service service = new Service();
private Locator locator = new Locator();
public Locator getLocator() {
return this.locator;
}
public String getBaseUrl() {
return this.baseUrl;
}
public boolean isEnabled() {
return this.enabled;
}
public int getFlushInterval() {
return this.flushInterval;
}
public Compression getCompression() {
return this.compression;
}
public Service getService() {
return this.service;
}
public void setBaseUrl(String baseUrl) {
this.baseUrl = baseUrl;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public void setFlushInterval(int flushInterval) {
this.flushInterval = flushInterval;
}
public void setCompression(Compression compression) {
this.compression = compression;
}
public void setService(Service service) {
this.service = service;
}
public void setLocator(Locator locator) {
this.locator = locator;
}
public Encoding getEncoding() {
return this.encoding;
}
public void setEncoding(Encoding encoding) {
this.encoding = encoding;
}
/** When enabled, spans are gzipped before sent to the zipkin server */
public static class Compression {
private boolean enabled = false;
public boolean isEnabled() {
return this.enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
}
/** When set will override the default {@code spring.application.name} value of the service id */
public static class Service {
/** The name of the service, from which the Span was sent via HTTP, that should appear in Zipkin */
private String name;
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
}
/** Configuration related to locating of the host name from service discovery.
* This property is NOT related to finding Zipkin via Service Disovery.
* To do so use the {@link ZipkinProperties#baseUrl} property with the
* service name set inside the URL.
*/
public static class Locator {
private Discovery discovery;
public Discovery getDiscovery() {
return this.discovery;
}
public void setDiscovery(Discovery discovery) {
this.discovery = discovery;
}
public static class Discovery {
/** Enabling of locating the host name via service discovery */
private boolean enabled;
public boolean isEnabled() {
return this.enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
}
}
}

View File

@@ -1,37 +0,0 @@
/*
* Copyright 2013-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;
import org.springframework.web.client.RestTemplate;
/**
* Implementations customize the {@link RestTemplate} used to report spans to Zipkin.
* For example, they can add an additional header needed by their environment.
*
* <p>Implementors must gzip according to {@link ZipkinProperties.Compression},
* for example by using the {@link DefaultZipkinRestTemplateCustomizer}.
*
* @author Marcin Grzejszczak
*
* @since 1.1.0
* @deprecated Please use spring-cloud-sleuth-zipkin2 to report spans to Zipkin
*/
@Deprecated
public interface ZipkinRestTemplateCustomizer {
void customize(RestTemplate restTemplate);
}

View File

@@ -1,258 +0,0 @@
/*
* Copyright 2013-2015 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;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import org.springframework.cloud.commons.util.IdUtils;
import org.springframework.cloud.sleuth.Log;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.SpanAdjuster;
import org.springframework.cloud.sleuth.SpanReporter;
import org.springframework.core.env.Environment;
import org.springframework.util.StringUtils;
import zipkin.Annotation;
import zipkin.BinaryAnnotation;
import zipkin.Constants;
import zipkin.Endpoint;
/**
* Listener of Sleuth events. Reports to Zipkin via {@link ZipkinSpanReporter}.
*
* @author Spencer Gibb
* @since 1.0.0
*/
public class ZipkinSpanListener implements SpanReporter {
private static final List<String> ZIPKIN_START_EVENTS = Arrays.asList(
Constants.CLIENT_RECV, Constants.SERVER_RECV
);
private static final List<String> RPC_EVENTS = Arrays.asList(
Constants.CLIENT_RECV, Constants.CLIENT_SEND, Constants.SERVER_RECV, Constants.SERVER_SEND
);
private static final org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory
.getLog(ZipkinSpanListener.class);
private static final Charset UTF_8 = Charset.forName("UTF-8");
private static final byte[] UNKNOWN_BYTES = "unknown".getBytes(UTF_8);
private final ZipkinSpanReporter reporter;
private final Environment environment;
private final List<SpanAdjuster> spanAdjusters;
/**
* Endpoint is the visible IP address of this service, the port it is listening on and
* the service name from discovery.
*/
// Visible for testing
final EndpointLocator endpointLocator;
public ZipkinSpanListener(ZipkinSpanReporter reporter, EndpointLocator endpointLocator,
Environment environment, List<SpanAdjuster> spanAdjusters) {
this.reporter = reporter;
this.endpointLocator = endpointLocator;
this.environment = environment;
this.spanAdjusters = spanAdjusters;
}
/**
* 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>
*
* When logging {@link Constants#CLIENT_SEND}, instrumentation should also log the {@link Constants#SERVER_ADDR}
* Check <a href="https://github.com/openzipkin/zipkin-java/blob/master/zipkin/src/main/java/zipkin/Constants.java#L28">Zipkin code</a>
* for more information
*/
// Visible for testing
zipkin.Span convert(Span span) {
//TODO: Consider adding support for the debug flag (related to #496)
Span convertedSpan = span;
for (SpanAdjuster adjuster : this.spanAdjusters) {
convertedSpan = adjuster.adjust(convertedSpan);
}
zipkin.Span.Builder zipkinSpan = zipkin.Span.builder();
Endpoint endpoint = this.endpointLocator.local();
processLogs(convertedSpan, zipkinSpan, endpoint);
addZipkinAnnotations(zipkinSpan, convertedSpan, endpoint);
addZipkinBinaryAnnotations(zipkinSpan, convertedSpan, endpoint);
// In the RPC span model, the client owns the timestamp and duration of the span. If we
// were propagated an id, we can assume that we shouldn't report timestamp or duration,
// rather let the client do that. Worst case we were propagated an unreported ID and
// Zipkin backfills timestamp and duration.
if (!convertedSpan.isRemote()) {
// don't report server-side timestamp on shared spans
if (Boolean.TRUE.equals(convertedSpan.isShared())) {
zipkinSpan.timestamp(null).duration(null);
} else {
zipkinSpan.timestamp(convertedSpan.getBegin() * 1000L);
if (!convertedSpan.isRunning()) { // duration is authoritative, only write when the span stopped
zipkinSpan.duration(calculateDurationInMicros(convertedSpan));
}
}
}
zipkinSpan.traceIdHigh(convertedSpan.getTraceIdHigh());
zipkinSpan.traceId(convertedSpan.getTraceId());
if (convertedSpan.getParents().size() > 0) {
if (convertedSpan.getParents().size() > 1) {
log.error("Zipkin doesn't support spans with multiple parents. Omitting "
+ "other parents for " + convertedSpan);
}
zipkinSpan.parentId(convertedSpan.getParents().get(0));
}
zipkinSpan.id(convertedSpan.getSpanId());
if (StringUtils.hasText(convertedSpan.getName())) {
zipkinSpan.name(convertedSpan.getName());
}
return zipkinSpan.build();
}
private void ensureLocalComponent(Span span, zipkin.Span.Builder zipkinSpan, Endpoint localEndpoint) {
if (span.tags().containsKey(Constants.LOCAL_COMPONENT)) {
return;
}
byte[] processId = span.getProcessId() != null
? span.getProcessId().toLowerCase().getBytes(UTF_8)
: UNKNOWN_BYTES;
BinaryAnnotation component = BinaryAnnotation.builder()
.type(BinaryAnnotation.Type.STRING)
.key("lc") // LOCAL_COMPONENT
.value(processId)
.endpoint(localEndpoint).build();
zipkinSpan.addBinaryAnnotation(component);
}
private void ensureServerAddr(Span span, zipkin.Span.Builder zipkinSpan) {
if (span.tags().containsKey(Span.SPAN_PEER_SERVICE_TAG_NAME)) {
zipkinSpan.addBinaryAnnotation(BinaryAnnotation.address(Constants.SERVER_ADDR,
Endpoint.builder().serviceName(
span.tags().get(Span.SPAN_PEER_SERVICE_TAG_NAME)).build()));
}
}
// Instead of going through the list of logs multiple times we're doing it only once
private void processLogs(Span span, zipkin.Span.Builder zipkinSpan, Endpoint endpoint) {
boolean notClientOrServer = true;
boolean hasClientSend = false;
boolean instanceIdToTag = false;
for (Log log : span.logs()) {
if (RPC_EVENTS.contains(log.getEvent())) {
instanceIdToTag = true;
}
if (ZIPKIN_START_EVENTS.contains(log.getEvent())) {
notClientOrServer = false;
}
if (Constants.CLIENT_SEND.equals(log.getEvent())) {
hasClientSend = !span.tags().containsKey(Constants.SERVER_ADDR);
}
}
if (notClientOrServer) {
// A zipkin span without any annotations cannot be queried, add special "lc" to avoid that.
ensureLocalComponent(span, zipkinSpan, endpoint);
}
if (hasClientSend) {
ensureServerAddr(span, zipkinSpan);
}
if (instanceIdToTag && this.environment != null) {
setInstanceIdIfPresent(zipkinSpan, endpoint, Span.INSTANCEID);
}
}
private void setInstanceIdIfPresent(zipkin.Span.Builder zipkinSpan,
Endpoint endpoint, String key) {
String property = IdUtils.getDefaultInstanceId(this.environment);
if (StringUtils.hasText(property)) {
addZipkinBinaryAnnotation(key, property, endpoint, zipkinSpan);
}
}
/**
* Add annotations from the sleuth Span.
*/
private void addZipkinAnnotations(zipkin.Span.Builder zipkinSpan,
Span span, Endpoint endpoint) {
for (Log ta : span.logs()) {
Annotation zipkinAnnotation = Annotation.builder()
.endpoint(endpoint)
.timestamp(ta.getTimestamp() * 1000) // Zipkin is in microseconds
.value(ta.getEvent()).build();
zipkinSpan.addAnnotation(zipkinAnnotation);
}
}
/**
* Adds binary annotation from the sleuth Span
*/
private void addZipkinBinaryAnnotations(zipkin.Span.Builder zipkinSpan,
Span span, Endpoint ep) {
for (Map.Entry<String, String> e : span.tags().entrySet()) {
addZipkinBinaryAnnotation(e.getKey(), e.getValue(), ep, zipkinSpan);
}
}
private void addZipkinBinaryAnnotation(String key, String value, Endpoint ep,
zipkin.Span.Builder zipkinSpan) {
BinaryAnnotation binaryAnn = BinaryAnnotation.builder()
.type(BinaryAnnotation.Type.STRING)
.key(key)
.value(value.getBytes(UTF_8))
.endpoint(ep).build();
zipkinSpan.addBinaryAnnotation(binaryAnn);
}
/**
* There could be instrumentation delay between span creation and the
* semantic start of the span (client send). When there's a difference,
* spans look confusing. Ex users expect duration to be client
* receive - send, but it is a little more than that. Rather than have
* to teach each user about the possibility of instrumentation overhead,
* we truncate absolute duration (span finish - create) to semantic
* duration (client receive - send)
*/
private long calculateDurationInMicros(Span span) {
Log clientSend = hasLog(Span.CLIENT_SEND, span);
Log clientReceived = hasLog(Span.CLIENT_RECV, span);
if (clientSend != null && clientReceived != null) {
return (clientReceived.getTimestamp() - clientSend.getTimestamp()) * 1000;
}
return span.getAccumulatedMicros();
}
private Log hasLog(String logName, Span span) {
for (Log log : span.logs()) {
if (logName.equals(log.getEvent())) {
return log;
}
}
return null;
}
@Override
public void report(Span span) {
if (span.isExportable()) {
this.reporter.report(convert(span));
} else {
if (log.isDebugEnabled()) {
log.debug("The span " + span + " will not be sent to Zipkin due to sampling");
}
}
}
}

View File

@@ -1,17 +0,0 @@
package org.springframework.cloud.sleuth.zipkin;
/**
* Contract for reporting Zipkin spans to Zipkin.
*
* @author Adrian Cole
* @since 1.0.0
* @deprecated Please use spring-cloud-sleuth-zipkin2 to report spans to Zipkin
*/
@Deprecated
public interface ZipkinSpanReporter {
/**
* Receives completed spans from {@link ZipkinSpanListener} and submits them to a Zipkin
* collector.
*/
void report(zipkin.Span span);
}

View File

@@ -1,3 +1,3 @@
# Auto Configuration
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.cloud.sleuth.zipkin.ZipkinAutoConfiguration
org.springframework.cloud.sleuth.zipkin2.ZipkinAutoConfiguration

View File

@@ -1,55 +0,0 @@
package org.springframework.cloud.sleuth.zipkin;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import zipkin.Endpoint;
import static org.assertj.core.api.BDDAssertions.then;
import static org.mockito.BDDMockito.given;
@RunWith(MockitoJUnitRunner.class)
public class FallbackHavingEndpointLocatorTests {
@Mock
ServiceInstanceEndpointLocator serviceInstanceEndpointLocator;
@Mock ServerPropertiesEndpointLocator serverPropertiesEndpointLocator;
Endpoint expectedEndpoint = Endpoint.builder()
.serviceName("my-tomcat").ipv4(127 << 24 | 1).port(8080).build();
@Test
public void should_use_system_property_locator_if_discovery_client_locator_is_not_present() {
given(this.serverPropertiesEndpointLocator.local()).willReturn(this.expectedEndpoint);
FallbackHavingEndpointLocator sut = new FallbackHavingEndpointLocator(null,
this.serverPropertiesEndpointLocator);
Endpoint endpoint = sut.local();
then(endpoint).isSameAs(this.expectedEndpoint);
}
@Test
public void should_use_system_property_locator_if_discovery_client_locator_throws_an_exception() {
given(this.serviceInstanceEndpointLocator.local()).willThrow(new RuntimeException());
given(this.serverPropertiesEndpointLocator.local()).willReturn(this.expectedEndpoint);
FallbackHavingEndpointLocator sut = new FallbackHavingEndpointLocator(this.serviceInstanceEndpointLocator,
this.serverPropertiesEndpointLocator);
Endpoint endpoint = sut.local();
then(endpoint).isSameAs(this.expectedEndpoint);
}
@Test
public void should_use_discovery_client_locator_by_default() {
given(this.serviceInstanceEndpointLocator.local()).willReturn(this.expectedEndpoint);
FallbackHavingEndpointLocator sut = new FallbackHavingEndpointLocator(this.serviceInstanceEndpointLocator,
this.serverPropertiesEndpointLocator);
Endpoint endpoint = sut.local();
then(endpoint).isSameAs(this.expectedEndpoint);
}
}

View File

@@ -1,221 +0,0 @@
package org.springframework.cloud.sleuth.zipkin;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Random;
import java.util.concurrent.atomic.AtomicReference;
import io.micrometer.core.instrument.Counter;
import org.junit.Rule;
import org.junit.Test;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.cloud.sleuth.DefaultSpanNamer;
import org.springframework.cloud.sleuth.TraceKeys;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.log.NoOpSpanLogger;
import org.springframework.cloud.sleuth.metric.CounterServiceBasedSpanMetricReporter;
import org.springframework.cloud.sleuth.metric.SpanMetricReporter;
import org.springframework.cloud.sleuth.sampler.AlwaysSampler;
import org.springframework.cloud.sleuth.trace.DefaultTracer;
import org.springframework.cloud.sleuth.util.ExceptionUtils;
import org.springframework.mock.env.MockEnvironment;
import org.springframework.web.client.RestTemplate;
import zipkin.Span;
import zipkin.junit.HttpFailure;
import zipkin.junit.ZipkinRule;
import zipkin.reporter.Encoding;
import static java.util.Arrays.asList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.BDDAssertions.then;
import static org.awaitility.Awaitility.await;
public class HttpZipkinSpanReporterTest {
@Rule public final ZipkinRule zipkin = new ZipkinRule();
Counter accepted = counter("accepted");
Counter dropped = counter("dropped");
SpanMetricReporter spanMetricReporter = new CounterServiceBasedSpanMetricReporter(this.accepted, this.dropped);
RestTemplate restTemplate = defaultRestTemplate();
HttpZipkinSpanReporter reporter = new HttpZipkinSpanReporter(restTemplate, this.zipkin.httpUrl(),
0, // so that tests can drive flushing explicitly
this.spanMetricReporter
);
@Test
public void reportDoesntDoIO() throws Exception {
this.reporter.report(span(1L, "foo"));
assertThat(this.zipkin.httpRequestCount()).isZero();
}
@Test
public void reportIncrementsAcceptedMetrics() throws Exception {
this.reporter.report(span(1L, "foo"));
assertThat(this.accepted.count()).isEqualTo(1);
assertThat(this.dropped.count()).isZero();
}
@Test
public void dropsWhenQueueIsFull() throws Exception {
for (int i = 0; i < 1001; i++)
this.reporter.report(span(1L, "foo"));
assertThat(this.accepted.count()).isEqualTo(1001);
assertThat(this.dropped.count()).isEqualTo(1);
}
@Test
public void postsSpans() throws Exception {
this.reporter.report(span(1L, "foo"));
this.reporter.report(span(2L, "bar"));
this.reporter.flush(); // manually flush the spans
// Ensure only one request was sent
assertThat(this.zipkin.httpRequestCount()).isEqualTo(1);
assertThat(this.zipkin.getTraces()).containsExactly(
asList(span(1L, "foo")),
asList(span(2L, "bar"))
);
}
@Test
public void postsCompressedSpans() throws Exception {
this.reporter = new HttpZipkinSpanReporter(restTemplateWithCompression(), this.zipkin.httpUrl(),
0, // so that tests can drive flushing explicitly
this.spanMetricReporter
);
this.reporter.report(span(1L, "foo"));
this.reporter.report(span(2L, "bar"));
this.reporter.flush(); // manually flush the spans
// Ensure only one request was sent
assertThat(this.zipkin.httpRequestCount()).isEqualTo(1);
assertThat(this.zipkin.getTraces()).containsExactly(
asList(span(1L, "foo")),
asList(span(2L, "bar"))
);
}
@Test
public void incrementsDroppedSpansWhenServerErrors() throws Exception {
this.zipkin.enqueueFailure(HttpFailure.sendErrorResponse(500, "Ouch"));
this.reporter.report(span(1L, "foo"));
this.reporter.report(span(2L, "bar"));
this.reporter.flush(); // manually flush the spans
assertThat(this.dropped.count()).isEqualTo(2);
}
@Test
public void incrementsDroppedSpansWhenServerDisconnects() throws Exception {
this.zipkin.enqueueFailure(HttpFailure.disconnectDuringBody());
this.reporter.report(span(1L, "foo"));
this.reporter.report(span(2L, "bar"));
this.reporter.flush(); // manually flush the spans
assertThat(this.dropped.count()).isEqualTo(2);
}
@Test
public void should_change_the_service_name_in_zipkin_to_the_manually_provided_one() {
AtomicReference<Span> receivedSpan = new AtomicReference<>();
Tracer tracer = new DefaultTracer(new AlwaysSampler(), new Random(), new DefaultSpanNamer(),
new NoOpSpanLogger(), new ZipkinSpanListener(receivedSpan::set,
new ServerPropertiesEndpointLocator(new ServerProperties(), new MockEnvironment(),
new ZipkinProperties()),
null, new ArrayList<>()), new TraceKeys());
// tag::service_name[]
org.springframework.cloud.sleuth.Span newSpan = tracer.createSpan("redis");
try {
newSpan.tag("redis.op", "get");
newSpan.tag("lc", "redis");
newSpan.logEvent(org.springframework.cloud.sleuth.Span.CLIENT_SEND);
// call redis service e.g
// return (SomeObj) redisTemplate.opsForHash().get("MYHASH", someObjKey);
} finally {
newSpan.tag("peer.service", "redisService");
newSpan.tag("peer.ipv4", "1.2.3.4");
newSpan.tag("peer.port", "1234");
newSpan.logEvent(org.springframework.cloud.sleuth.Span.CLIENT_RECV);
tracer.close(newSpan);
}
// end::service_name[]
then(tracer.getCurrentSpan()).isNull();
then(ExceptionUtils.getLastException()).isNull();
then(receivedSpan.get().binaryAnnotations)
.flatExtracting(input -> input.key, input -> new String(input.value))
.contains("peer.service", "redisService");
}
@Test
public void testSenderThriftEncoding() {
ZipkinProperties zipkinProperties = new ZipkinProperties();
zipkinProperties.setEncoding(Encoding.THRIFT);
zipkinProperties.setBaseUrl(zipkin.httpUrl());
HttpZipkinSpanReporter httpZipkinSpanReporter = new HttpZipkinSpanReporter(restTemplate(zipkinProperties)
, zipkinProperties.getBaseUrl(), 1, spanMetricReporter, zipkinProperties.getEncoding());
Tracer tracer = new DefaultTracer(new AlwaysSampler(), new Random(), new DefaultSpanNamer(),
new NoOpSpanLogger(),new ZipkinSpanListener(httpZipkinSpanReporter,
new ServerPropertiesEndpointLocator(new ServerProperties(), new MockEnvironment(),
zipkinProperties),
null, Collections.emptyList()), new TraceKeys());
tracer.close(tracer.createSpan("foo"));
httpZipkinSpanReporter.flush();
await().until(() -> zipkin.getTraces().size() == 1);
assertThat(zipkin.getTraces().size()).isEqualTo(1);
}
static Span span(long traceId, String spanName) {
return Span.builder().traceId(traceId).id(traceId).name(spanName).build();
}
private RestTemplate restTemplate(ZipkinProperties zipkinProperties) {
RestTemplate restTemplate = new RestTemplate();
new DefaultZipkinRestTemplateCustomizer(zipkinProperties).customize(restTemplate);
return restTemplate;
}
private RestTemplate defaultRestTemplate() {
return restTemplate(new ZipkinProperties());
}
private RestTemplate restTemplateWithCompression() {
ZipkinProperties zipkinProperties = new ZipkinProperties();
zipkinProperties.getCompression().setEnabled(true);
return restTemplate(zipkinProperties);
}
private Counter counter(final String name) {
return new Counter() {
private double counter;
@Override public void increment(double amount) {
this.counter = this.counter + amount;
}
@Override public double count() {
return this.counter;
}
@Override public Id getId() {
return new Id(name, Collections.emptyList(), "unit", "description");
}
};
}
}

View File

@@ -1,94 +0,0 @@
/*
* Copyright 2015 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;
import java.net.InetAddress;
import java.net.UnknownHostException;
import org.junit.Test;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.mock.env.MockEnvironment;
import static org.assertj.core.api.Assertions.assertThat;
public class ServerPropertiesEndpointLocatorTests {
public static final byte[] ADDRESS1234 = { 1, 2, 3, 4 };
@Test
public void portDefaultsTo8080() throws UnknownHostException {
ServerPropertiesEndpointLocator locator = new ServerPropertiesEndpointLocator(
new ServerProperties(), new MockEnvironment(), new ZipkinProperties());
assertThat(locator.local().port).isEqualTo((short) 8080);
}
@Test
public void portFromServerProperties() throws UnknownHostException {
ServerProperties properties = new ServerProperties();
properties.setPort(1234);
ServerPropertiesEndpointLocator locator = new ServerPropertiesEndpointLocator(
properties, new MockEnvironment(), new ZipkinProperties());
assertThat(locator.local().port).isEqualTo((short) 1234);
}
@Test
public void portDefaultsToLocalhost() throws UnknownHostException {
MockEnvironment environment = new MockEnvironment();
environment.setProperty("spring.cloud.client.ipAddress", String.valueOf(1 << 24 | 2 << 16 | 3 << 8 | 4));
ServerPropertiesEndpointLocator locator = new ServerPropertiesEndpointLocator(
new ServerProperties(), environment, new ZipkinProperties());
assertThat(locator.local().ipv4).isEqualTo(1 << 24 | 2 << 16 | 3 << 8 | 4);
}
@Test
public void hostFromServerPropertiesIp() throws UnknownHostException {
ServerProperties properties = new ServerProperties();
properties.setAddress(InetAddress.getByAddress(ADDRESS1234));
ServerPropertiesEndpointLocator locator = new ServerPropertiesEndpointLocator(
properties, new MockEnvironment(), new ZipkinProperties());
assertThat(locator.local().ipv4).isEqualTo(1 << 24 | 2 << 16 | 3 << 8 | 4);
}
@Test
public void appNameFromProperties() throws UnknownHostException {
ServerProperties properties = new ServerProperties();
ZipkinProperties zipkinProperties = new ZipkinProperties();
zipkinProperties.getService().setName("foo");
ServerPropertiesEndpointLocator locator = new ServerPropertiesEndpointLocator(
properties, new MockEnvironment(), zipkinProperties);
assertThat(locator.local().serviceName).isEqualTo("foo");
}
@Test
public void negativePortFromServerProperties() throws UnknownHostException {
ServerProperties properties = new ServerProperties();
properties.setPort(-1);
ServerPropertiesEndpointLocator locator = new ServerPropertiesEndpointLocator(
properties, new MockEnvironment(), new ZipkinProperties());
assertThat(locator.local().port).isEqualTo((short) 8080);
}
}

View File

@@ -1,95 +0,0 @@
package org.springframework.cloud.sleuth.zipkin;
import org.junit.Test;
import org.mockito.Mockito;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.cloud.client.serviceregistry.Registration;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author Marcin Wielgus
*/
public class ServiceInstanceEndpointLocatorConfigurationTest {
@Test
public void endpointLocatorShouldDefaultToServerPropertiesEndpointLocator() {
ConfigurableApplicationContext ctxt = new SpringApplication(
EmptyConfiguration.class).run("--spring.jmx.enabled=false",
"--spring.cloud.discovery.client.composite-indicator.enabled=false");
assertThat(ctxt.getBean(EndpointLocator.class))
.isInstanceOf(ServerPropertiesEndpointLocator.class);
ctxt.close();
}
@Test
public void endpointLocatorShouldDefaultToServerPropertiesEndpointLocatorEvenWhenDiscoveryClientPresent() {
ConfigurableApplicationContext ctxt = new SpringApplication(
ConfigurationWithRegistration.class).run("--spring.jmx.enabled=false",
"--spring.cloud.discovery.client.composite-indicator.enabled=false");
assertThat(ctxt.getBean(EndpointLocator.class))
.isInstanceOf(ServerPropertiesEndpointLocator.class);
ctxt.close();
}
@Test
public void endpointLocatorShouldRespectExistingEndpointLocator() {
ConfigurableApplicationContext ctxt = new SpringApplication(
ConfigurationWithCustomLocator.class).run("--spring.jmx.enabled=false",
"--spring.cloud.discovery.client.composite-indicator.enabled=false");
assertThat(ctxt.getBean(EndpointLocator.class))
.isSameAs(ConfigurationWithCustomLocator.locator);
ctxt.close();
}
@Test
public void endpointLocatorShouldBeFallbackHavingEndpointLocatorWhenAskedTo() {
ConfigurableApplicationContext ctxt = new SpringApplication(
ConfigurationWithRegistration.class).run("--spring.jmx.enabled=false",
"--spring.zipkin.locator.discovery.enabled=true",
"--spring.cloud.discovery.client.composite-indicator.enabled=false");
assertThat(ctxt.getBean(EndpointLocator.class))
.isInstanceOf(FallbackHavingEndpointLocator.class);
ctxt.close();
}
@Test
public void endpointLocatorShouldRespectExistingEndpointLocatorEvenWhenAskedToBeDiscovery() {
ConfigurableApplicationContext ctxt = new SpringApplication(
ConfigurationWithRegistration.class,
ConfigurationWithCustomLocator.class).run("--spring.jmx.enabled=false",
"--spring.zipkin.locator.discovery.enabled=true",
"--spring.cloud.discovery.client.composite-indicator.enabled=false");
assertThat(ctxt.getBean(EndpointLocator.class))
.isSameAs(ConfigurationWithCustomLocator.locator);
ctxt.close();
}
@Configuration
@EnableAutoConfiguration
public static class EmptyConfiguration {
}
@Configuration
@EnableAutoConfiguration
public static class ConfigurationWithRegistration {
@Bean public Registration registration() {
return Mockito.mock(Registration.class);
}
}
@Configuration
@EnableAutoConfiguration
public static class ConfigurationWithCustomLocator {
static EndpointLocator locator = Mockito.mock(EndpointLocator.class);
@Bean public EndpointLocator getEndpointLocator() {
return locator;
}
}
}

View File

@@ -1,143 +0,0 @@
/*
* Copyright 2013-2017 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;
import java.net.URI;
import java.util.Map;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.commons.util.InetUtils;
import org.springframework.cloud.sleuth.zipkin.ServiceInstanceEndpointLocator.NoServiceInstanceAvailableException;
import static org.assertj.core.api.BDDAssertions.then;
import zipkin.Endpoint;
/**
* @author Marcin Grzejszczak
*/
@RunWith(MockitoJUnitRunner.class)
public class ServiceInstanceEndpointLocatorTest {
@Test(expected = NoServiceInstanceAvailableException.class)
public void should_throw_exception_when_no_instances_are_available() throws Exception {
ServiceInstanceEndpointLocator endpointLocator = endpointLocator(null);
endpointLocator.local();
}
private ServiceInstanceEndpointLocator endpointLocator(ServiceInstance serviceInstance) {
return endpointLocator(serviceInstance, new ZipkinProperties());
}
private ServiceInstanceEndpointLocator endpointLocator(ServiceInstance serviceInstance, ZipkinProperties zipkinProperties) {
return new ServiceInstanceEndpointLocator(serviceInstance, zipkinProperties);
}
@Test
public void should_create_endpoint_with_0_ip_when_exception_occurs_on_resolving_host() throws Exception {
ServiceInstanceEndpointLocator endpointLocator = endpointLocator(serviceInstanceWithInvalidHost());
Endpoint local = endpointLocator.local();
then(local.serviceName).isEqualTo("serviceid");
then(local.port).isEqualTo((short)8_000);
then(local.ipv4).isEqualTo(0);
}
@Test
public void should_create_valid_endpoint_when_proper_host_is_passed() throws Exception {
ServiceInstanceEndpointLocator endpointLocator = endpointLocator(serviceInstanceWithValidHost());
Endpoint local = endpointLocator.local();
then(local.serviceName).isEqualTo("serviceid");
then(local.port).isEqualTo((short)8_000);
then(local.ipv4).isEqualTo(InetUtils.getIpAddressAsInt("localhost"));
}
@Test
public void should_create_endpoint_with_overridden_name() throws Exception {
ZipkinProperties zipkinProperties = new ZipkinProperties();
zipkinProperties.getService().setName("foo");
ServiceInstanceEndpointLocator locator = endpointLocator(serviceInstanceWithValidHost(), zipkinProperties);
Endpoint local = locator.local();
then(local.serviceName).isEqualTo("foo");
then(local.port).isEqualTo((short)8_000);
then(local.ipv4).isEqualTo(InetUtils.getIpAddressAsInt("localhost"));
}
private ServiceInstance serviceInstanceWithInvalidHost() {
return new ServiceInstance() {
@Override public String getServiceId() {
return "serviceId";
}
@Override public String getHost() {
throw new RuntimeException();
}
@Override public int getPort() {
return 8000;
}
@Override public boolean isSecure() {
return false;
}
@Override public URI getUri() {
return null;
}
@Override public Map<String, String> getMetadata() {
return null;
}
};
}
private ServiceInstance serviceInstanceWithValidHost() {
return new ServiceInstance() {
@Override public String getServiceId() {
return "serviceId";
}
@Override public String getHost() {
return "localhost";
}
@Override public int getPort() {
return 8000;
}
@Override public boolean isSecure() {
return false;
}
@Override public URI getUri() {
return null;
}
@Override public Map<String, String> getMetadata() {
return null;
}
};
}
}

View File

@@ -1,104 +0,0 @@
package org.springframework.cloud.sleuth.zipkin;
import java.io.IOException;
import java.net.URI;
import java.util.Map;
import org.awaitility.Awaitility;
import org.junit.ClassRule;
import org.junit.Test;
import org.junit.runner.RunWith;
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.loadbalancer.LoadBalancerClient;
import org.springframework.cloud.client.loadbalancer.LoadBalancerRequest;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.SpanReporter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.junit4.SpringRunner;
import zipkin.junit.ZipkinRule;
import static org.assertj.core.api.BDDAssertions.then;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = ZipkinDiscoveryClientTests.Config.class, properties = {
"spring.zipkin.baseUrl=http://zipkin/",
"spring.cloud.discovery.client.composite-indicator.enabled=false" })
public class ZipkinDiscoveryClientTests {
@ClassRule public static ZipkinRule ZIPKIN_RULE = new ZipkinRule();
@Autowired SpanReporter spanReporter;
@Test
public void shouldUseDiscoveryClientToFindZipkinUrlIfPresent() throws Exception {
Span span = Span.builder().traceIdHigh(1L).traceId(2L).spanId(3L).name("foo")
.build();
this.spanReporter.report(span);
Awaitility.await().untilAsserted(() -> then(ZIPKIN_RULE.httpRequestCount()).isGreaterThan(0));
}
@Configuration
@EnableAutoConfiguration
static class Config {
@Bean LoadBalancerClient loadBalancerClient() {
return new LoadBalancerClient() {
@Override public <T> T execute(String serviceId,
LoadBalancerRequest<T> request) throws IOException {
return null;
}
@Override public <T> T execute(String serviceId,
ServiceInstance serviceInstance, LoadBalancerRequest<T> request)
throws IOException {
return null;
}
@Override public URI reconstructURI(ServiceInstance instance,
URI original) {
return null;
}
@Override public ServiceInstance choose(String serviceId) {
return new ServiceInstance() {
@Override
public String getServiceId() {
return "zipkin";
}
@Override
public String getHost() {
return "localhost";
}
@Override
public int getPort() {
return URI.create(ZIPKIN_RULE.httpUrl()).getPort();
}
@Override
public boolean isSecure() {
return false;
}
@Override
public URI getUri() {
return URI.create(ZIPKIN_RULE.httpUrl());
}
@Override
public Map<String, String> getMetadata() {
return null;
}
};
}
};
}
}
}

View File

@@ -1,372 +0,0 @@
/*
* Copyright 2013-2017 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;
import org.assertj.core.api.Condition;
import zipkin.Constants;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import javax.annotation.PostConstruct;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.sleuth.Sampler;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.SpanAdjuster;
import org.springframework.cloud.sleuth.SpanReporter;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.sampler.AlwaysSampler;
import org.springframework.cloud.sleuth.zipkin.ZipkinSpanListenerTests.TestConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.mock.env.MockEnvironment;
import org.springframework.test.context.junit4.SpringRunner;
import zipkin.Endpoint;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.assertEquals;
/**
* @author Dave Syer
*
*/
@SpringBootTest(classes = TestConfiguration.class)
@RunWith(SpringRunner.class)
public class ZipkinSpanListenerTests {
@Autowired Tracer tracer;
@Autowired TestConfiguration test;
@Autowired ZipkinSpanListener spanListener;
@Autowired ZipkinSpanReporter spanReporter;
@Autowired MockEnvironment mockEnvironment;
@Autowired EndpointLocator endpointLocator;
@PostConstruct
public void init() {
this.test.zipkinSpans.clear();
}
Span parent = Span.builder().traceId(1L).name("http:parent").remote(true).build();
/** Sleuth timestamps are millisecond granularity while zipkin is microsecond. */
@Test
public void convertsTimestampToMicrosecondsAndSetsDurationToAccumulatedMicros() {
Span span = Span.builder().traceId(1L).name("http:api").build();
long start = System.currentTimeMillis();
span.logEvent("hystrix/retry"); // System.currentTimeMillis
span.stop();
zipkin.Span result = this.spanListener.convert(span);
assertThat(result.timestamp)
.isEqualTo(span.getBegin() * 1000);
assertThat(result.duration)
.isEqualTo(span.getAccumulatedMicros());
assertThat(result.annotations.get(0).timestamp)
.isGreaterThanOrEqualTo(start * 1000)
.isLessThanOrEqualTo(System.currentTimeMillis() * 1000);
}
@Test
public void setsTheDurationToTheDifferenceBetweenCRandCS()
throws InterruptedException {
Span span = Span.builder().traceId(1L).name("http:api").build();
span.logEvent(Span.CLIENT_SEND);
Thread.sleep(10);
span.logEvent(Span.CLIENT_RECV);
Thread.sleep(20);
span.stop();
zipkin.Span result = this.spanListener.convert(span);
assertThat(result.timestamp).isEqualTo(span.getBegin() * 1000);
long clientSendTimestamp = span.logs().stream()
.filter(log -> Span.CLIENT_SEND.equals(log.getEvent())).findFirst().get()
.getTimestamp();
long clientRecvTimestamp = span.logs().stream()
.filter(log -> Span.CLIENT_RECV.equals(log.getEvent())).findFirst().get()
.getTimestamp();
assertThat(result.duration).isNotEqualTo(span.getAccumulatedMicros())
.isEqualTo((clientRecvTimestamp - clientSendTimestamp) * 1000);
}
/** Zipkin's duration should only be set when the span is finished. */
@Test
public void doesntSetDurationWhenStillRunning() {
Span span = Span.builder().traceId(1L).name("http:api").build();
zipkin.Span result = this.spanListener.convert(span);
assertThat(result.timestamp)
.isGreaterThan(0); // sanity check it did start
assertThat(result.duration)
.isNull();
}
/**
* In the RPC span model, the client owns the timestamp and duration of the span. If
* we were propagated an id, we can assume that we shouldn't report timestamp or
* duration, rather let the client do that. Worst case we were propagated an
* unreported ID and Zipkin backfills timestamp and duration.
*/
@Test
public void doesntSetTimestampOrDurationWhenRemote() {
this.parent.stop();
zipkin.Span result = this.spanListener.convert(this.parent);
assertThat(result.timestamp)
.isNull();
assertThat(result.duration)
.isNull();
}
/** Sleuth host corresponds to annotation/binaryAnnotation.host in zipkin. */
@Test
public void annotationsIncludeHost() {
this.parent.logEvent("hystrix/retry");
this.parent.tag("spring-boot/version", "1.3.1.RELEASE");
zipkin.Span result = this.spanListener.convert(this.parent);
assertThat(result.annotations.get(0).endpoint)
.isEqualTo(this.spanListener.endpointLocator.local());
assertThat(result.binaryAnnotations.get(0).endpoint)
.isEqualTo(result.annotations.get(0).endpoint);
}
/** zipkin's Endpoint.serviceName should never be null. */
@Test
public void localEndpointIncludesServiceName() {
assertThat(this.spanListener.endpointLocator.local().serviceName)
.isNotEmpty();
}
/**
* In zipkin, the service context is attached to annotations. Sleuth spans that have
* no annotations will get an "lc" one, which allows them to be queryable in zipkin by
* service name.
*/
@Test
public void spanWithoutAnnotationsLogsComponent() {
Span context = this.tracer.createSpan("http:foo");
this.tracer.close(context);
assertEquals(1, this.test.zipkinSpans.size());
assertThat(this.test.zipkinSpans.get(0).binaryAnnotations.get(0).value)
.isEqualTo("unknown".getBytes()); // TODO: "unknown" bc process id, documented as not nullable, is null.
}
@Test
public void rpcAnnotations() {
Span context = this.tracer.createSpan("http:child", this.parent);
context.logEvent(Span.CLIENT_SEND);
logServerReceived(this.parent);
logServerSent(this.spanListener, this.parent);
this.tracer.close(context);
assertEquals(2, this.test.zipkinSpans.size());
}
void logServerReceived(Span parent) {
if (parent != null && parent.isRemote()) {
parent.logEvent(Span.SERVER_RECV);
}
}
void logServerSent(SpanReporter spanReporter, Span parent) {
if (parent != null && parent.isRemote()) {
parent.logEvent(Span.SERVER_SEND);
spanReporter.report(parent);
}
}
@Test
public void appendsLocalComponentTagIfNoZipkinLogIsPresent() {
this.parent.logEvent("hystrix/retry");
this.parent.stop();
zipkin.Span result = this.spanListener.convert(this.parent);
assertThat(result.binaryAnnotations)
.extracting(input -> input.key)
.contains(Constants.LOCAL_COMPONENT);
}
@Test
public void appendServerAddressTagIfClientLogIsPresentWhenPeerServiceIsPresent() {
this.parent.logEvent(Constants.CLIENT_SEND);
this.parent.tag(Span.SPAN_PEER_SERVICE_TAG_NAME, "fooservice");
this.parent.stop();
zipkin.Span result = this.spanListener.convert(this.parent);
assertThat(result.binaryAnnotations)
.filteredOn("key", Constants.SERVER_ADDR)
.extracting(input -> input.endpoint)
.hasSize(1)
.has(new Condition<List<? extends Endpoint>>() {
@Override public boolean matches(List<? extends Endpoint> value) {
Endpoint endpoint = value.get(0);
return endpoint.serviceName.equals("fooservice") && endpoint.ipv4 == 0;
}
});
}
@Test
public void doesNotAppendServerAddressTagIfClientLogIsPresent() {
this.parent.logEvent(Constants.CLIENT_SEND);
this.parent.stop();
zipkin.Span result = this.spanListener.convert(this.parent);
assertThat(result.binaryAnnotations)
.filteredOn("key", Constants.SERVER_ADDR)
.isEmpty();
}
@Test
public void converts128BitTraceId() {
Span span = Span.builder().traceIdHigh(1L).traceId(2L).spanId(3L).name("foo").build();
zipkin.Span result = this.spanListener.convert(span);
assertThat(result.traceIdHigh).isEqualTo(span.getTraceIdHigh());
assertThat(result.traceId).isEqualTo(span.getTraceId());
}
@Test
public void shouldReuseServerAddressTag() {
this.parent.logEvent(Constants.CLIENT_SEND);
this.parent.tag(Span.SPAN_PEER_SERVICE_TAG_NAME, "fooservice");
this.parent.stop();
zipkin.Span result = this.spanListener.convert(this.parent);
assertThat(result.binaryAnnotations)
.filteredOn("key", Constants.SERVER_ADDR)
.extracting(input -> input.endpoint.serviceName)
.containsOnly("fooservice");
}
@Test
public void shouldNotReportToZipkinWhenSpanIsNotExportable() {
Span span = Span.builder().exportable(false).build();
this.spanListener.report(span);
assertThat(this.test.zipkinSpans).isEmpty();
}
@Test
public void shouldAddClientServiceIdTagWhenSpanContainsRpcEvent() {
this.parent.logEvent(Span.CLIENT_SEND);
this.mockEnvironment.setProperty("vcap.application.instance_id", "foo");
zipkin.Span result = this.spanListener.convert(this.parent);
assertThat(result.binaryAnnotations)
.filteredOn("key", Span.INSTANCEID)
.extracting(input -> input.value)
.containsOnly("foo".getBytes());
}
@Test
public void shouldNotAddAnyServiceIdTagWhenSpanContainsRpcEventAndThereIsNoEnvironment() {
this.parent.logEvent(Span.CLIENT_RECV);
ZipkinSpanListener spanListener = new ZipkinSpanListener(this.spanReporter,
this.endpointLocator, null, new ArrayList<>());
zipkin.Span result = spanListener.convert(this.parent);
assertThat(result.binaryAnnotations)
.filteredOn("key", Span.INSTANCEID)
.extracting(input -> input.value)
.isEmpty();
}
@Test
public void should_adjust_span_before_reporting_it() {
this.parent.logEvent(Span.CLIENT_RECV);
ZipkinSpanListener spanListener = new ZipkinSpanListener(this.spanReporter,
this.endpointLocator, null, Arrays.asList(
(SpanAdjuster) span -> Span.builder().from(span).name("foo").build(),
(SpanAdjuster) span -> Span.builder().from(span).name(span.getName() + "bar").build()
));
zipkin.Span result = spanListener.convert(this.parent);
assertThat(result.name).isEqualTo("foobar");
}
@Test
public void shouldRemoveTimestampAndDurationForNonRemoteSharedSpan() {
Span span = Span.builder()
.name("foo")
.exportable(false)
.remote(false)
.shared(true)
.build();
zipkin.Span result = this.spanListener.convert(span);
assertThat(result.duration).isNull();
assertThat(result.timestamp).isNull();
}
@Test
public void shouldNotRemoveTimestampAndDurationForNonRemoteNonSharedSpan() {
Span span = Span.builder()
.name("foo")
.exportable(false)
.remote(false)
.shared(false)
.build();
span.stop();
zipkin.Span result = this.spanListener.convert(span);
assertThat(result.duration).isNotNull();
assertThat(result.timestamp).isNotNull();
}
@Configuration
@EnableAutoConfiguration
protected static class TestConfiguration {
private List<zipkin.Span> zipkinSpans = new ArrayList<>();
@Bean
public Sampler sampler() {
return new AlwaysSampler();
}
@Bean
public ZipkinSpanReporter reporter() {
return this.zipkinSpans::add;
}
@Bean @Primary MockEnvironment mockEnvironment() {
return new MockEnvironment();
}
}
}

View File

@@ -1,37 +0,0 @@
/*
* Copyright 2013-2017 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;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = ZipkinWithDisabledSleuthTests.Config.class)
@TestPropertySource(properties = "spring.sleuth.enabled=false")
public class ZipkinWithDisabledSleuthTests {
@Test public void shouldStartContext() {
}
@EnableAutoConfiguration
static class Config {
}
}

View File

@@ -1,137 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2013-2017 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.
-->
<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-zipkin2</artifactId>
<packaging>jar</packaging>
<name>Spring Cloud Sleuth Zipkin v2</name>
<description>Spring Cloud Sleuth Zipkin v2</description>
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth</artifactId>
<version>2.0.0.BUILD-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-commons</artifactId>
</dependency>
<!--<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-context</artifactId>
<optional>true</optional>
</dependency>-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-actuator</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>io.zipkin.zipkin2</groupId>
<artifactId>zipkin</artifactId>
</dependency>
<dependency>
<groupId>io.zipkin.reporter2</groupId>
<artifactId>zipkin-reporter</artifactId>
</dependency>
<dependency>
<groupId>io.zipkin.reporter2</groupId>
<artifactId>zipkin-sender-kafka11</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>io.zipkin.reporter2</groupId>
<artifactId>zipkin-sender-amqp-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.amqp</groupId>
<artifactId>spring-rabbit</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-messaging</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.awaitility</groupId>
<artifactId>awaitility</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>mockwebserver</artifactId>
<version>3.9.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@@ -1,3 +0,0 @@
# Auto Configuration
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.cloud.sleuth.zipkin2.ZipkinAutoConfiguration

View File

@@ -9,8 +9,8 @@
<relativePath>..</relativePath>
</parent>
<artifactId>spring-cloud-starter-zipkin</artifactId>
<name>spring-cloud-starter-zipkin</name>
<description>Spring Cloud Starter</description>
<name>Spring Cloud Starter Zipkin</name>
<description>Spring Cloud Starter Zipkin</description>
<properties>
<main.basedir>${basedir}/../..</main.basedir>
</properties>

View File

@@ -1,27 +0,0 @@
<?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>
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth</artifactId>
<version>2.0.0.BUILD-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<artifactId>spring-cloud-starter-zipkin2</artifactId>
<name>spring-cloud-starter-zipkin2</name>
<description>Spring Cloud Starter Zipkin v2</description>
<properties>
<main.basedir>${basedir}/../..</main.basedir>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-zipkin2</artifactId>
</dependency>
</dependencies>
</project>

View File

@@ -1 +0,0 @@
provides: spring-platform-netflix-core, eureka-client