Merge branch 'master' into 2.0.x
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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[]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user