Merge branch '1.3.x'

This commit is contained in:
Marcin Grzejszczak
2018-02-12 12:12:39 +01:00
4 changed files with 165 additions and 42 deletions

View File

@@ -169,9 +169,6 @@ to `true`.
==== Live examples
.First, send a request
http://docssleuth-service1.cfapps.io/start[Click here to send the request]
.Click Pivotal Web Services icon to see it live!
[caption="Click Pivotal Web Services icon to see it live!"]
image::https://raw.githubusercontent.com/spring-cloud/spring-cloud-sleuth/{branch}/docs/src/main/asciidoc/images/pws.png["Zipkin deployed on Pivotal Web Services", link="http://docssleuth-zipkin-server.cfapps.io/", width=150, height=74]
@@ -183,8 +180,8 @@ image::https://raw.githubusercontent.com/spring-cloud/spring-cloud-sleuth/{branc
.Click Pivotal Web Services icon to see it live!
[caption="Click Pivotal Web Services icon to see it live!"]
image::https://raw.githubusercontent.com/spring-cloud/spring-cloud-sleuth/{branch}/docs/src/main/asciidoc/images/pws.png["Zipkin deployed on Pivotal Web Services", link="http://docssleuth-zipkin-server.cfapps.io/zipkin/dependency/", width=150, height=74]
http://docssleuth-zipkin-server.cfapps.io/zipkin/dependency/[Click here to see it live!]
image::https://raw.githubusercontent.com/spring-cloud/spring-cloud-sleuth/{branch}/docs/src/main/asciidoc/images/pws.png["Zipkin deployed on Pivotal Web Services", link="http://docssleuth-zipkin-server.cfapps.io/dependency", width=150, height=74]
http://docssleuth-zipkin-server.cfapps.io/dependency[Click here to see it live!]
==== Log correlation
@@ -343,7 +340,10 @@ Example of setting baggage on a span:
[source,java]
----
Unresolved directive in intro.adoc - include::https://raw.githubusercontent.com/spring-cloud/spring-cloud-sleuth/master/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/brave/instrument/web/multiple/MultipleHopsIntegrationTests.java[tags=baggage,indent=0]
Span initialSpan = this.tracer.nextSpan().name("span").start();
try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(initialSpan)) {
ExtraFieldPropagation.set("foo", "bar");
ExtraFieldPropagation.set("UPPER_CASE", "someValue");
}
----
@@ -361,7 +361,10 @@ IMPORTANT: Remember that the span needs to be in scope!
[source,java]
----
Unresolved directive in intro.adoc - include::https://raw.githubusercontent.com/spring-cloud/spring-cloud-sleuth/master/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/brave/instrument/web/multiple/MultipleHopsIntegrationTests.java[tags=baggage_tag,indent=0]
initialSpan.tag("foo",
ExtraFieldPropagation.get(initialSpan.context(), "foo"));
initialSpan.tag("UPPER_CASE",
ExtraFieldPropagation.get(initialSpan.context(), "UPPER_CASE"));
----
=== Adding to the project
@@ -567,14 +570,14 @@ a baggage element then it will be sent downstream either via HTTP or messaging t
* Provides a way to create / continue spans and add tags and logs via annotations.
* Provides simple metrics of accepted / dropped spans.
* 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.
* Spring Cloud Sleuth is http://opentracing.io/[OpenTracing] compatible
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

@@ -17,22 +17,23 @@
package org.springframework.cloud.sleuth.instrument.web.client;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import javax.annotation.PostConstruct;
import brave.http.HttpTracing;
import brave.spring.web.TracingClientHttpRequestInterceptor;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.web.client.RestTemplateCustomizer;
import org.springframework.cloud.sleuth.instrument.web.TraceWebServletAutoConfiguration;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.web.client.RestTemplate;
@@ -63,44 +64,32 @@ public class TraceWebClientAutoConfiguration {
@Configuration
protected static class TraceInterceptorConfiguration {
@Autowired(required = false)
private Collection<RestTemplate> restTemplates;
@Autowired
private ApplicationContext applicationContext;
@Autowired
private TracingClientHttpRequestInterceptor clientInterceptor;
@PostConstruct
public void init() {
if (this.restTemplates != null) {
for (RestTemplate restTemplate : this.restTemplates) {
new RestTemplateInterceptorInjector(this.clientInterceptor)
.inject(restTemplate);
}
Map<String, RestTemplate> restTemplates = BeanFactoryUtils
.beansOfTypeIncludingAncestors(this.applicationContext,
RestTemplate.class);
for (RestTemplate restTemplate : restTemplates.values()) {
new RestTemplateInterceptorInjector(
this.clientInterceptor).inject(restTemplate);
}
}
}
@Autowired(required = false)
private Collection<RestTemplate> restTemplates;
@Autowired
private TracingClientHttpRequestInterceptor traceRestTemplateInterceptor;
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
RestTemplateCustomizer traceRestTemplateCustomizer() {
final TracingClientHttpRequestInterceptor interceptor = this.traceRestTemplateInterceptor;
return restTemplate ->
new RestTemplateInterceptorInjector(interceptor).inject(restTemplate);
}
@PostConstruct
public void init() {
if (this.restTemplates != null) {
for (RestTemplate restTemplate : this.restTemplates) {
new RestTemplateInterceptorInjector(
this.traceRestTemplateInterceptor).inject(restTemplate);
}
@Bean
@Order
RestTemplateCustomizer traceRestTemplateCustomizer() {
return new RestTemplateCustomizer() {
@Override public void customize(RestTemplate restTemplate) {
new RestTemplateInterceptorInjector(TraceInterceptorConfiguration.this.clientInterceptor)
.inject(restTemplate);
}
};
}
}
}

View File

@@ -0,0 +1,133 @@
/*
* Copyright 2013-2018 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.instrument.web.client;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import brave.spring.web.TracingClientHttpRequestInterceptor;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.boot.web.client.RestTemplateCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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.test.context.junit4.SpringRunner;
import org.springframework.web.client.RestTemplate;
import static org.assertj.core.api.BDDAssertions.then;
/**
* @author Marcin Grzejszczak
*/
@RunWith(SpringRunner.class)
@SpringBootTest(classes = TraceWebClientAutoConfigurationTests.Config.class)
public class TraceWebClientAutoConfigurationTests {
@Autowired @Qualifier("firstRestTemplate") RestTemplate restTemplate;
@Autowired @Qualifier("secondRestTemplate") RestTemplate secondRestTemplate;
@Test
public void should_add_rest_template_interceptors() {
assertInterceptorsOrder(assertInterceptorsNotEmpty(this.restTemplate));
assertInterceptorsOrder(assertInterceptorsNotEmpty(this.secondRestTemplate));
}
private List<ClientHttpRequestInterceptor> assertInterceptorsNotEmpty(RestTemplate restTemplate) {
then(restTemplate).isNotNull();
List<ClientHttpRequestInterceptor> interceptors = restTemplate
.getInterceptors();
then(interceptors).isNotEmpty();
return interceptors;
}
private void assertInterceptorsOrder(
List<ClientHttpRequestInterceptor> interceptors) {
int traceInterceptorIndex = -1;
int myInterceptorIndex = -1;
int mySecondInterceptorIndex = -1;
for (int i = 0; i < interceptors.size(); i++) {
if (interceptors.get(i) instanceof TracingClientHttpRequestInterceptor) {
traceInterceptorIndex = i;
} else if (interceptors.get(i) instanceof MyClientHttpRequestInterceptor) {
myInterceptorIndex = i;
} else if (interceptors.get(i) instanceof MySecondClientHttpRequestInterceptor) {
mySecondInterceptorIndex = i;
}
}
then(traceInterceptorIndex)
.isGreaterThanOrEqualTo(0)
.isLessThan(myInterceptorIndex)
.isLessThan(mySecondInterceptorIndex);
}
@Configuration
@EnableAutoConfiguration
static class Config {
@Bean
@Qualifier("firstRestTemplate")
RestTemplate restTemplate(RestTemplateBuilder restTemplateBuilder) {
return restTemplateBuilder
.additionalInterceptors(new MyClientHttpRequestInterceptor())
.build();
}
@Bean
@Qualifier("secondRestTemplate")
RestTemplate secondRestTemplate() {
RestTemplate restTemplate = new RestTemplate();
restTemplate.setInterceptors(
Arrays.asList(new MyClientHttpRequestInterceptor(),
new MySecondClientHttpRequestInterceptor()));
return restTemplate;
}
@Bean
RestTemplateCustomizer myRestTemplateCustomizer() {
return restTemplate -> {
restTemplate.getInterceptors().add(0, new MySecondClientHttpRequestInterceptor());
};
}
}
}
class MyClientHttpRequestInterceptor implements ClientHttpRequestInterceptor {
@Override public ClientHttpResponse intercept(HttpRequest request, byte[] body,
ClientHttpRequestExecution execution) throws IOException {
return execution.execute(request, body);
}
}
class MySecondClientHttpRequestInterceptor implements ClientHttpRequestInterceptor {
@Override public ClientHttpResponse intercept(HttpRequest request, byte[] body,
ClientHttpRequestExecution execution) throws IOException {
return execution.execute(request, body);
}
}

View File

@@ -403,8 +403,6 @@ public class WebClientTests {
@Override public void customize(RestTemplate restTemplate) {
this.executed = true;
then(restTemplate.getInterceptors().get(0)).isInstanceOf(
TracingClientHttpRequestInterceptor.class);
}
public boolean isExecuted() {