Merge branch 'master' into 2.0.x

This commit is contained in:
Marcin Grzejszczak
2017-08-24 14:36:43 +02:00
6 changed files with 74 additions and 2 deletions

View File

@@ -421,6 +421,21 @@ And you could register them like this:
include::../../../..//spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/TraceCustomFilterResponseInjectorTests.java[tags=configuration,indent=0]
----
=== TraceFilter
You can also modify the behaviour of the `TraceFilter` - the component that is responsible
for processing the input HTTP request and adding tags basing on the HTTP response. You can customize
the tags, or modify the response headers by registering your own instance of the `TraceFilter` bean.
In the following example we will register the `TraceFilter` bean and we will add the
`ZIPKIN-TRACE-ID` response header containing the current Span's trace id. Also we will
add to the Span a tag with key `custom` and a value `tag`.
[source,java]
----
include::../../../..//spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/TraceFilterIntegrationTests.java[tags=response_headers,indent=0]
----
=== Custom SA tag in Zipkin
Sometimes you want to create a manual Span that will wrap a call to an external service which is not instrumented.

View File

@@ -31,6 +31,7 @@ import javax.servlet.http.HttpServletResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.cloud.sleuth.ErrorParser;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.SpanReporter;
@@ -105,7 +106,7 @@ public class TraceFilter extends GenericFilterBean {
private UrlPathHelper urlPathHelper = new UrlPathHelper();
public TraceFilter(BeanFactory beanFactory) {
this(beanFactory, Pattern.compile(SleuthWebProperties.DEFAULT_SKIP_PATTERN));
this(beanFactory, skipPattern(beanFactory));
}
public TraceFilter(BeanFactory beanFactory, Pattern skipPattern) {
@@ -113,6 +114,22 @@ public class TraceFilter extends GenericFilterBean {
this.skipPattern = skipPattern;
}
private static Pattern skipPattern(BeanFactory beanFactory) {
try {
SkipPatternProvider patternProvider = beanFactory
.getBean(SkipPatternProvider.class);
// the null value will not happen on production but might happen in tests
if (patternProvider != null) {
return patternProvider.skipPattern();
}
} catch (NoSuchBeanDefinitionException e) {
if (log.isDebugEnabled()) {
log.debug("The default SkipPatternProvider implementation is missing, will fallback to a default value of patterns");
}
}
return Pattern.compile(SleuthWebProperties.DEFAULT_SKIP_PATTERN);
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
FilterChain filterChain) throws IOException, ServletException {

View File

@@ -19,6 +19,7 @@ import org.springframework.beans.factory.BeanFactory;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
@@ -88,6 +89,7 @@ public class TraceWebServletAutoConfiguration {
}
@Bean
@ConditionalOnMissingBean
public TraceFilter traceFilter(BeanFactory beanFactory,
SkipPatternProvider skipPatternProvider) {
return new TraceFilter(beanFactory, skipPatternProvider.skipPattern());

View File

@@ -9,6 +9,7 @@ import org.junit.runner.RunWith;
import org.mockito.BDDMockito;
import org.mockito.Mockito;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.sleuth.NoOpSpanReporter;
@@ -68,6 +69,8 @@ public class TraceFilterAlwaysSamplerIntegrationTests extends AbstractMvcIntegra
private BeanFactory beanFactory() {
BeanFactory beanFactory = Mockito.mock(BeanFactory.class);
BDDMockito.given(beanFactory.getBean(SkipPatternProvider.class))
.willThrow(new NoSuchBeanDefinitionException("foo"));
BDDMockito.given(beanFactory.getBean(Tracer.class)).willReturn(this.tracer);
BDDMockito.given(beanFactory.getBean(TraceKeys.class)).willReturn(this.traceKeys);
BDDMockito.given(beanFactory.getBean(HttpSpanExtractor.class)).willReturn(this.spanExtractor);

View File

@@ -4,6 +4,8 @@ import java.util.Optional;
import java.util.Random;
import java.util.concurrent.CompletableFuture;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.After;
@@ -11,6 +13,7 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.MDC;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.autoconfigure.ManagementServerProperties;
import org.springframework.boot.test.context.SpringBootTest;
@@ -60,7 +63,7 @@ public class TraceFilterIntegrationTests extends AbstractMvcIntegrationTest {
}
@Test
public void should_create_and_return_trace_in_HTTP_header() throws Exception {
public void should_create_a_trace() throws Exception {
whenSentPingWithoutTracingData();
then(this.spanAccumulator.getSpans()).hasSize(1);
@@ -158,6 +161,17 @@ public class TraceFilterIntegrationTests extends AbstractMvcIntegrationTest {
then(new ListOfSpans(this.spanAccumulator.getSpans())).hasServerSideSpansInProperOrder();
}
@Test
public void should_return_custom_response_headers_when_custom_trace_filter_gets_registered() throws Exception {
Long expectedTraceId = new Random().nextLong();
MvcResult mvcResult = whenSentPingWithTraceId(expectedTraceId);
then(ExceptionUtils.getLastException()).isNull();
then(mvcResult.getResponse().getHeader("ZIPKIN-TRACE-ID")).isEqualTo(Span.idToHex(expectedTraceId));
then(new ListOfSpans(this.spanAccumulator.getSpans())).hasASpanWithTagEqualTo("custom", "tag");
}
@Override
protected void configureMockMvcBuilder(DefaultMockMvcBuilder mockMvcBuilder) {
mockMvcBuilder.addFilters(this.traceFilter);
@@ -290,5 +304,23 @@ public class TraceFilterIntegrationTests extends AbstractMvcIntegrationTest {
Sampler alwaysSampler() {
return new AlwaysSampler();
}
//tag::response_headers[]
@Bean
TraceFilter myTraceFilter(BeanFactory beanFactory, final Tracer tracer) {
return new TraceFilter(beanFactory) {
@Override protected void addResponseTags(HttpServletResponse response,
Throwable e) {
// execute the default behaviour
super.addResponseTags(response, e);
// for readability we're returning trace id in a hex form
response.addHeader("ZIPKIN-TRACE-ID",
Span.idToHex(tracer.getCurrentSpan().getTraceId()));
// we can also add some custom tags
tracer.addTag("custom", "tag");
}
};
}
//end::response_headers[]
}
}

View File

@@ -28,6 +28,7 @@ import org.mockito.BDDMockito;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.cloud.sleuth.DefaultSpanNamer;
import org.springframework.cloud.sleuth.ErrorParser;
import org.springframework.cloud.sleuth.ExceptionMessageErrorParser;
@@ -529,6 +530,8 @@ public class TraceFilterTests {
}
private BeanFactory beanFactory() {
BDDMockito.given(beanFactory.getBean(SkipPatternProvider.class))
.willThrow(new NoSuchBeanDefinitionException("foo"));
BDDMockito.given(beanFactory.getBean(Tracer.class)).willReturn(this.tracer);
BDDMockito.given(beanFactory.getBean(TraceKeys.class)).willReturn(this.traceKeys);
BDDMockito.given(beanFactory.getBean(HttpSpanExtractor.class)).willReturn(this.spanExtractor);