Merge branch 'master' into 2.0.x

This commit is contained in:
Marcin Grzejszczak
2017-07-15 19:52:43 +02:00
8 changed files with 204 additions and 10 deletions

View File

@@ -322,6 +322,7 @@ Example of setting baggage on a span:
----
Span initialSpan = this.tracer.createSpan("span");
initialSpan.setBaggageItem("foo", "bar");
initialSpan.setBaggageItem("UPPER_CASE", "someValue");
----
===== Baggage vs. Span Tags

View File

@@ -484,6 +484,26 @@ Stream based span reporting).
spring.zipkin.locator.discovery.enabled: true
----
== Sending spans to Zipkin
By default if you add `spring-cloud-starter-zipkin` as a dependency to your project,
when the span is closed, it will be sent to Zipkin over HTTP. The communication
is asynchronous. You can configure the URL by setting the `spring.zipkin.baseUrl`
property as follows:
[source,yaml]
----
spring.zipkin.baseUrl: http://192.168.99.100:9411/
----
If you want to find Zipkin via service discovery it's enough to pass the
Zipkin's service id inside the URL (example for `zipkinserver` service id)
[source,yaml]
----
spring.zipkin.baseUrl: http://zipkinserver/
----
== Span Data as Messages
You can accumulate and send span data over

View File

@@ -226,12 +226,6 @@
<version>3.0.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.github.tomakehurst</groupId>
<artifactId>wiremock</artifactId>
<version>2.6.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>pl.pragmatists</groupId>
<artifactId>JUnitParams</artifactId>

View File

@@ -88,6 +88,11 @@
<artifactId>zipkin-junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.awaitility</groupId>
<artifactId>awaitility</artifactId>
<scope>test</scope>
</dependency>
<!-- otherwise spring boot's version of okhttp kicks zipkin-junit's deps out of alignment -->
<dependency>
<groupId>com.squareup.okhttp3</groupId>

View File

@@ -16,6 +16,7 @@
package org.springframework.cloud.sleuth.zipkin;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
@@ -24,9 +25,11 @@ import org.springframework.beans.factory.annotation.Value;
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.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.commons.util.InetUtils;
import org.springframework.cloud.sleuth.Sampler;
@@ -64,6 +67,7 @@ import org.springframework.web.client.RestTemplate;
public class ZipkinAutoConfiguration {
@Autowired(required = false) List<SpanAdjuster> spanAdjusters = new ArrayList<>();
@Autowired ZipkinUrlExtractor extractor;
@Bean
@ConditionalOnMissingBean
@@ -71,10 +75,51 @@ public class ZipkinAutoConfiguration {
ZipkinRestTemplateCustomizer zipkinRestTemplateCustomizer) {
RestTemplate restTemplate = new RestTemplate();
zipkinRestTemplateCustomizer.customize(restTemplate);
return new HttpZipkinSpanReporter(restTemplate, zipkin.getBaseUrl(), zipkin.getFlushInterval(),
String zipkinUrl = this.extractor.zipkinUrl(zipkin);
return new HttpZipkinSpanReporter(restTemplate, zipkinUrl, zipkin.getFlushInterval(),
spanMetricReporter);
}
@Configuration
@ConditionalOnClass(DiscoveryClient.class)
static class DiscoveryClientZipkinUrlExtractorConfiguration {
@Autowired(required = false) DiscoveryClient discoveryClient;
@Bean
ZipkinUrlExtractor zipkinUrlExtractor() {
final DiscoveryClient discoveryClient = this.discoveryClient;
return new ZipkinUrlExtractor() {
@Override
public String zipkinUrl(ZipkinProperties zipkinProperties) {
if (discoveryClient != null) {
URI uri = URI.create(zipkinProperties.getBaseUrl());
String host = uri.getHost();
List<ServiceInstance> instances = discoveryClient.getInstances(host);
if (!instances.isEmpty()) {
return instances.get(0).getUri().toString();
}
}
return zipkinProperties.getBaseUrl();
}
};
}
}
@Configuration
@ConditionalOnMissingClass("org.springframework.cloud.client.discovery.DiscoveryClient")
static class DefaultZipkinUrlExtractorConfiguration {
@Bean
ZipkinUrlExtractor zipkinUrlExtractor() {
return new ZipkinUrlExtractor() {
@Override
public String zipkinUrl(ZipkinProperties zipkinProperties) {
return zipkinProperties.getBaseUrl();
}
};
}
}
@Bean
@ConditionalOnMissingBean
public ZipkinRestTemplateCustomizer zipkinRestTemplateCustomizer(ZipkinProperties zipkinProperties) {
@@ -156,3 +201,7 @@ public class ZipkinAutoConfiguration {
}
}
interface ZipkinUrlExtractor {
String zipkinUrl(ZipkinProperties zipkinProperties);
}

View File

@@ -26,7 +26,10 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
*/
@ConfigurationProperties("spring.zipkin")
public class ZipkinProperties {
/** URL of the zipkin query server instance. */
/** 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/";
private boolean enabled = true;
private int flushInterval = 1;

View File

@@ -0,0 +1,118 @@
package org.springframework.cloud.sleuth.zipkin;
import static org.assertj.core.api.BDDAssertions.then;
import static org.springframework.cloud.sleuth.zipkin.ZipkinDiscoveryClientTests.ZIPKIN_RULE;
import java.io.IOException;
import java.net.URI;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.assertj.core.api.BDDAssertions;
import org.awaitility.Awaitility;
import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Rule;
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.discovery.DiscoveryClient;
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 org.springframework.util.SocketUtils;
import zipkin.junit.ZipkinRule;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = ZipkinDiscoveryClientTests.Config.class,
properties = "spring.zipkin.baseUrl=http://zipkin/")
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
DiscoveryClient client() {
return new ZipkinDiscoveryClient();
}
}
}
class ZipkinDiscoveryClient implements DiscoveryClient {
@Override
public String description() {
return "";
}
@Override
public ServiceInstance getLocalServiceInstance() {
return null;
}
@Override
public List<ServiceInstance> getInstances(String s) {
if ("zipkin".equals(s)) {
return Collections.singletonList(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;
}
});
}
return Collections.emptyList();
}
@Override
public List<String> getServices() {
return Collections.singletonList("zipkin");
}
}

View File

@@ -17,11 +17,16 @@
package org.springframework.cloud.sleuth.zipkin;
import org.assertj.core.api.Condition;
import org.junit.Ignore;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import zipkin.Constants;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import javax.annotation.PostConstruct;
import org.junit.Test;
@@ -56,7 +61,6 @@ import static org.junit.Assert.assertEquals;
public class ZipkinSpanListenerTests {
@Autowired Tracer tracer;
@Autowired ApplicationContext application;
@Autowired TestConfiguration test;
@Autowired ZipkinSpanListener spanListener;
@Autowired ZipkinSpanReporter spanReporter;
@@ -337,4 +341,4 @@ public class ZipkinSpanListenerTests {
}
}
}