diff --git a/docs/src/main/asciidoc/spring-cloud-sleuth.adoc b/docs/src/main/asciidoc/spring-cloud-sleuth.adoc index c8424392a..8af6ec017 100644 --- a/docs/src/main/asciidoc/spring-cloud-sleuth.adoc +++ b/docs/src/main/asciidoc/spring-cloud-sleuth.adoc @@ -1012,7 +1012,9 @@ Features from this section can be disabled by providing the `spring.sleuth.web.e Via the `TraceFilter` all sampled incoming requests result in creation of a Span. That Span's name is `http:` + the path to which the request was sent. E.g. if the request was sent to `/foo/bar` then the name will be `http:/foo/bar`. You can configure which URIs you would like to skip via the `spring.sleuth.web.skipPattern` property. If you have `ManagementServerProperties` on classpath then - its value of `contextPath` gets appended to the provided skip pattern. + its value of `contextPath` gets appended to the provided skip pattern. If you want to reuse the + Sleuth's default skip patterns and just append your own, pass those patterns via + the `spring.sleuth.web.additionalSkipPattern`. ==== HandlerInterceptor @@ -1032,7 +1034,9 @@ If your controller returns a `Callable` or a `WebAsyncTask` Spring Cloud Sleuth Via the `TraceWebFilter` all sampled incoming requests result in creation of a Span. That Span's name is `http:` + the path to which the request was sent. E.g. if the request was sent to `/foo/bar` then the name will be `http:/foo/bar`. You can configure which URIs you would like to skip via the `spring.sleuth.web.skipPattern` property. If you have `ManagementServerProperties` on classpath then - its value of `contextPath` gets appended to the provided skip pattern. + its value of `contextPath` gets appended to the provided skip pattern. If you want to reuse the + Sleuth's default skip patterns and just append your own, pass those patterns via + the `spring.sleuth.web.additionalSkipPattern`. === HTTP client integration @@ -1125,7 +1129,9 @@ If you want to skip Span creation for some `@Scheduled` annotated classes you ca `spring.sleuth.scheduled.skipPattern` with a regular expression that will match the fully qualified name of the `@Scheduled` annotated class. -TIP: If you are using `spring-cloud-sleuth-stream` and `spring-cloud-netflix-hystrix-stream` together, Span will be created for each Hystrix metrics and sent to Zipkin. This may be annoying. You can prevent this by setting `spring.sleuth.scheduled.skipPattern=org.springframework.cloud.netflix.hystrix.stream.HystrixStreamTask` +TIP: If you are using `spring-cloud-sleuth-stream` and `spring-cloud-netflix-hystrix-stream` together, Span will be created for +each Hystrix metrics and sent to Zipkin. This may be annoying. You can prevent this by setting +`spring.sleuth.scheduled.skipPattern=org.springframework.cloud.netflix.hystrix.stream.HystrixStreamTask` ==== Executor, ExecutorService and ScheduledExecutorService diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/SleuthWebProperties.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/SleuthWebProperties.java index 9020ab332..96cd13900 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/SleuthWebProperties.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/SleuthWebProperties.java @@ -41,6 +41,12 @@ public class SleuthWebProperties { */ private String skipPattern = DEFAULT_SKIP_PATTERN; + /** + * Additional pattern for URLs that should be skipped in tracing. + * This will be appended to the {@link SleuthWebProperties#skipPattern} + */ + private String additionalSkipPattern; + private Client client; public boolean isEnabled() { @@ -59,6 +65,14 @@ public class SleuthWebProperties { this.skipPattern = skipPattern; } + public String getAdditionalSkipPattern() { + return this.additionalSkipPattern; + } + + public void setAdditionalSkipPattern(String additionalSkipPattern) { + this.additionalSkipPattern = additionalSkipPattern; + } + public Client getClient() { return this.client; } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceWebAutoConfiguration.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceWebAutoConfiguration.java index 45c3426ef..4277dfda8 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceWebAutoConfiguration.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceWebAutoConfiguration.java @@ -77,21 +77,23 @@ public class TraceWebAutoConfiguration { ManagementServerProperties managementServerProperties, SleuthWebProperties sleuthWebProperties) { String skipPattern = sleuthWebProperties.getSkipPattern(); + String additionalSkipPattern = sleuthWebProperties.getAdditionalSkipPattern(); String contextPath = managementServerProperties.getServlet().getContextPath(); if (StringUtils.hasText(skipPattern) && StringUtils.hasText(contextPath)) { - return Pattern.compile(skipPattern + "|" + contextPath + ".*"); + return Pattern.compile(combinedPattern(skipPattern + "|" + contextPath + ".*", additionalSkipPattern)); } else if (StringUtils.hasText(contextPath)) { - return Pattern.compile(contextPath + ".*"); + return Pattern.compile(combinedPattern(contextPath + ".*", additionalSkipPattern)); } - return defaultSkipPattern(skipPattern); + return defaultSkipPattern(skipPattern, additionalSkipPattern); } @Bean @ConditionalOnMissingBean(ManagementServerProperties.class) public SkipPatternProvider defaultSkipPatternBeanIfManagementServerPropsArePresent(SleuthWebProperties sleuthWebProperties) { - return defaultSkipPatternProvider(sleuthWebProperties.getSkipPattern()); + return defaultSkipPatternProvider(sleuthWebProperties.getSkipPattern(), + sleuthWebProperties.getAdditionalSkipPattern()); } } @@ -100,17 +102,28 @@ public class TraceWebAutoConfiguration { @ConditionalOnMissingBean( SkipPatternProvider.class) public SkipPatternProvider defaultSkipPatternBean(SleuthWebProperties sleuthWebProperties) { - return defaultSkipPatternProvider(sleuthWebProperties.getSkipPattern()); + return defaultSkipPatternProvider(sleuthWebProperties.getSkipPattern(), + sleuthWebProperties.getAdditionalSkipPattern()); } private static SkipPatternProvider defaultSkipPatternProvider( - final String skipPattern) { - return () -> defaultSkipPattern(skipPattern); + final String skipPattern, final String additionalSkipPattern) { + return () -> defaultSkipPattern(skipPattern, additionalSkipPattern); } - private static Pattern defaultSkipPattern(String skipPattern) { - return StringUtils.hasText(skipPattern) ? Pattern.compile(skipPattern) - : Pattern.compile(SleuthWebProperties.DEFAULT_SKIP_PATTERN); + private static Pattern defaultSkipPattern(String skipPattern, String additionalSkipPattern) { + return Pattern.compile(combinedPattern(skipPattern, additionalSkipPattern)); + } + + private static String combinedPattern(String skipPattern, String additionalSkipPattern) { + String pattern = skipPattern; + if (!StringUtils.hasText(skipPattern)) { + pattern = SleuthWebProperties.DEFAULT_SKIP_PATTERN; + } + if (StringUtils.hasText(additionalSkipPattern)) { + return pattern + "|" + additionalSkipPattern; + } + return pattern; } } diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/SkipPatternProviderConfigTest.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/SkipPatternProviderConfigTest.java index 8df05463d..7df40583b 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/SkipPatternProviderConfigTest.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/SkipPatternProviderConfigTest.java @@ -38,6 +38,17 @@ public class SkipPatternProviderConfigTest { then(pattern.pattern()).isEqualTo("foo.*|bar.*|/management/context.*"); } + @Test + public void should_combine_skip_pattern_management_context_and_additional_pattern_when_all_are_not_empty() throws Exception { + SleuthWebProperties sleuthWebProperties = new SleuthWebProperties(); + sleuthWebProperties.setSkipPattern("foo.*|bar.*"); + sleuthWebProperties.setAdditionalSkipPattern("baz.*|faz.*"); + Pattern pattern = TraceWebAutoConfiguration.SkipPatternProviderConfig.getPatternForManagementServerProperties( + managementServerPropertiesWithContextPath(), sleuthWebProperties); + + then(pattern.pattern()).isEqualTo("foo.*|bar.*|/management/context.*|baz.*|faz.*"); + } + @Test public void should_pick_skip_pattern_when_its_not_empty_and_management_context_is_empty() throws Exception { SleuthWebProperties sleuthWebProperties = new SleuthWebProperties(); @@ -48,6 +59,17 @@ public class SkipPatternProviderConfigTest { then(pattern.pattern()).isEqualTo("foo.*|bar.*"); } + @Test + public void should_pick_skip_pattern_and_additional_pattern_when_its_not_empty_and_management_context_is_empty() throws Exception { + SleuthWebProperties sleuthWebProperties = new SleuthWebProperties(); + sleuthWebProperties.setSkipPattern("foo.*|bar.*"); + sleuthWebProperties.setAdditionalSkipPattern("baz.*|faz.*"); + + Pattern pattern = TraceWebAutoConfiguration.SkipPatternProviderConfig.getPatternForManagementServerProperties(new ManagementServerProperties(), sleuthWebProperties); + + then(pattern.pattern()).isEqualTo("foo.*|bar.*|baz.*|faz.*"); + } + @Test public void should_pick_management_context_when_skip_patterns_is_empty_and_context_path_is_not() throws Exception { SleuthWebProperties sleuthWebProperties = new SleuthWebProperties(); @@ -59,6 +81,18 @@ public class SkipPatternProviderConfigTest { then(pattern.pattern()).isEqualTo("/management/context.*"); } + @Test + public void should_pick_management_context_and_additional_pattern_when_skip_patterns_is_empty_and_context_path_is_not() throws Exception { + SleuthWebProperties sleuthWebProperties = new SleuthWebProperties(); + sleuthWebProperties.setSkipPattern(""); + sleuthWebProperties.setAdditionalSkipPattern("baz.*|faz.*"); + + Pattern pattern = TraceWebAutoConfiguration.SkipPatternProviderConfig.getPatternForManagementServerProperties( + managementServerPropertiesWithContextPath(), sleuthWebProperties); + + then(pattern.pattern()).isEqualTo("/management/context.*|baz.*|faz.*"); + } + @Test public void should_pick_default_pattern_when_both_management_context_and_skip_patterns_are_empty() throws Exception { SleuthWebProperties sleuthWebProperties = new SleuthWebProperties(); @@ -72,6 +106,20 @@ public class SkipPatternProviderConfigTest { then(pattern.pattern()).isEqualTo(SleuthWebProperties.DEFAULT_SKIP_PATTERN); } + @Test + public void should_pick_default_pattern_with_additional_pattern_when_both_management_context_and_skip_patterns_are_empty() throws Exception { + SleuthWebProperties sleuthWebProperties = new SleuthWebProperties(); + sleuthWebProperties.setSkipPattern(""); + sleuthWebProperties.setAdditionalSkipPattern("baz.*|faz.*"); + ManagementServerProperties managementServerProperties = new ManagementServerProperties(); + managementServerProperties.getServlet().setContextPath(""); + + Pattern pattern = TraceWebAutoConfiguration.SkipPatternProviderConfig.getPatternForManagementServerProperties( + managementServerProperties, sleuthWebProperties); + + then(pattern.pattern()).isEqualTo(SleuthWebProperties.DEFAULT_SKIP_PATTERN + "|baz.*|faz.*"); + } + private ManagementServerProperties managementServerPropertiesWithContextPath() { ManagementServerProperties managementServerProperties = new ManagementServerProperties(); managementServerProperties.getServlet().setContextPath("/management/context");