Skip to content

Commit 6cae6b8

Browse files
ask4gillesgeoand
authored andcommitted
Register skipPattern for SB actuator endpoints dynamically. (#100)
1 parent e043077 commit 6cae6b8

16 files changed

+1132
-66
lines changed

opentracing-spring-web-starter/pom.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,12 @@
7171
<optional>true</optional>
7272
</dependency>
7373

74+
<dependency>
75+
<groupId>org.springframework.boot</groupId>
76+
<artifactId>spring-boot-starter-actuator</artifactId>
77+
<optional>true</optional>
78+
</dependency>
79+
7480
<dependency>
7581
<groupId>io.opentracing</groupId>
7682
<artifactId>opentracing-mock</artifactId>

opentracing-spring-web-starter/src/main/java/io/opentracing/contrib/spring/web/starter/ServerTracingAutoConfiguration.java

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,10 @@
1616
import java.util.Arrays;
1717
import java.util.Collections;
1818
import java.util.List;
19+
import java.util.regex.Pattern;
1920

2021
import org.springframework.beans.factory.ObjectProvider;
22+
import org.springframework.beans.factory.annotation.Qualifier;
2123
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
2224
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
2325
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
@@ -47,22 +49,27 @@
4749
/**
4850
* @author Pavol Loffay
4951
* @author Eddú Meléndez
52+
* @author Gilles Robert
5053
*/
5154
@Configuration
5255
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
5356
@ConditionalOnBean(Tracer.class)
54-
@AutoConfigureAfter(TracerAutoConfiguration.class)
57+
@AutoConfigureAfter({TracerAutoConfiguration.class, SkipPatternAutoConfiguration.class})
5558
@EnableConfigurationProperties(WebTracingProperties.class)
5659
@ConditionalOnClass(WebMvcConfigurerAdapter.class)
5760
@ConditionalOnProperty(name = "opentracing.spring.web.enabled", havingValue = "true", matchIfMissing = true)
5861
public class ServerTracingAutoConfiguration {
62+
5963
private static final Log log = LogFactory.getLog(ServerTracingAutoConfiguration.class);
6064

65+
private final Pattern skipPattern;
6166
private final ObjectProvider<List<ServletFilterSpanDecorator>> servletFilterSpanDecorator;
6267
private final ObjectProvider<List<HandlerInterceptorSpanDecorator>> interceptorSpanDecorator;
6368

64-
public ServerTracingAutoConfiguration(ObjectProvider<List<ServletFilterSpanDecorator>> servletFilterSpanDecorator,
69+
public ServerTracingAutoConfiguration(@Qualifier("skipPattern") Pattern skipPattern,
70+
ObjectProvider<List<ServletFilterSpanDecorator>> servletFilterSpanDecorator,
6571
ObjectProvider<List<HandlerInterceptorSpanDecorator>> interceptorSpanDecorator) {
72+
this.skipPattern = skipPattern;
6673
this.servletFilterSpanDecorator = servletFilterSpanDecorator;
6774
this.interceptorSpanDecorator = interceptorSpanDecorator;
6875
}
@@ -72,17 +79,16 @@ public ServerTracingAutoConfiguration(ObjectProvider<List<ServletFilterSpanDecor
7279
public FilterRegistrationBean tracingFilter(Tracer tracer, WebTracingProperties tracingConfiguration) {
7380
log.info(format("Creating %s bean with %s mapped to %s, skip pattern is \"%s\"",
7481
FilterRegistrationBean.class.getSimpleName(), TracingFilter.class.getSimpleName(),
75-
tracingConfiguration.getUrlPatterns().toString(),
76-
tracingConfiguration.getSkipPattern()));
82+
tracingConfiguration.getUrlPatterns().toString(), skipPattern));
7783

7884
List<ServletFilterSpanDecorator> decorators = servletFilterSpanDecorator.getIfAvailable();
7985
if (CollectionUtils.isEmpty(decorators)) {
8086
decorators = Collections.singletonList(ServletFilterSpanDecorator.STANDARD_TAGS);
8187
}
8288

83-
TracingFilter tracingFilter = new TracingFilter(tracer, decorators, tracingConfiguration.getSkipPattern());
89+
TracingFilter tracingFilter = new TracingFilter(tracer, decorators, skipPattern);
8490

85-
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(tracingFilter);
91+
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean<>(tracingFilter);
8692
filterRegistrationBean.setUrlPatterns(tracingConfiguration.getUrlPatterns());
8793
filterRegistrationBean.setOrder(tracingConfiguration.getOrder());
8894
filterRegistrationBean.setAsyncSupported(true);
@@ -106,8 +112,6 @@ public void addInterceptors(InterceptorRegistry registry) {
106112
}
107113

108114
registry.addInterceptor(new TracingHandlerInterceptor(tracer, decorators));
109-
110-
super.addInterceptors(registry);
111115
}
112116
};
113117
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
/**
2+
* Copyright 2016-2019 The OpenTracing Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5+
* in compliance with the License. You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software distributed under the License
10+
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11+
* or implied. See the License for the specific language governing permissions and limitations under
12+
* the License.
13+
*/
14+
package io.opentracing.contrib.spring.web.starter;
15+
16+
import java.util.ArrayList;
17+
import java.util.Collection;
18+
import java.util.List;
19+
import java.util.Optional;
20+
import java.util.regex.Pattern;
21+
import java.util.stream.Collectors;
22+
23+
import org.springframework.beans.factory.annotation.Autowired;
24+
import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties;
25+
import org.springframework.boot.actuate.autoconfigure.web.server.ConditionalOnManagementPort;
26+
import org.springframework.boot.actuate.autoconfigure.web.server.ManagementPortType;
27+
import org.springframework.boot.actuate.autoconfigure.web.server.ManagementServerProperties;
28+
import org.springframework.boot.actuate.endpoint.EndpointsSupplier;
29+
import org.springframework.boot.actuate.endpoint.web.ExposableWebEndpoint;
30+
import org.springframework.boot.actuate.endpoint.web.PathMappedEndpoint;
31+
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
32+
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
33+
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
34+
import org.springframework.boot.autoconfigure.web.ServerProperties;
35+
import org.springframework.context.annotation.Bean;
36+
import org.springframework.context.annotation.Configuration;
37+
import org.springframework.util.StringUtils;
38+
39+
import io.opentracing.contrib.spring.web.webfilter.SkipPattern;
40+
41+
/**
42+
* @author Gilles Robert
43+
*/
44+
@Configuration
45+
@ConditionalOnProperty(name = "opentracing.spring.web.enabled", havingValue = "true", matchIfMissing = true)
46+
public class SkipPatternAutoConfiguration {
47+
48+
@Autowired(required = false)
49+
private List<SkipPattern> patterns = new ArrayList<>();
50+
51+
@Bean(name = "skipPattern")
52+
public Pattern skipPattern() {
53+
return Pattern.compile(this.patterns
54+
.stream()
55+
.map(SkipPattern::pattern)
56+
.filter(Optional::isPresent).map(Optional::get)
57+
.map(Pattern::pattern)
58+
.collect(Collectors.joining("|")));
59+
}
60+
61+
@Configuration
62+
@ConditionalOnClass(ManagementServerProperties.class)
63+
@ConditionalOnProperty(value = "opentracing.spring.web.ignoreAutoConfiguredSkipPatterns", havingValue = "false", matchIfMissing = true)
64+
protected static class ManagementSkipPatternProviderConfig {
65+
66+
static Optional<Pattern> getPatternForManagementServerProperties(
67+
ManagementServerProperties managementServerProperties) {
68+
String contextPath = managementServerProperties.getServlet().getContextPath();
69+
if (StringUtils.hasText(contextPath)) {
70+
return Optional.of(Pattern.compile(contextPath + ".*"));
71+
}
72+
return Optional.empty();
73+
}
74+
75+
@Bean
76+
@ConditionalOnBean(ManagementServerProperties.class)
77+
public SkipPattern skipPatternForManagementServerProperties(
78+
final ManagementServerProperties managementServerProperties) {
79+
return () -> getPatternForManagementServerProperties(managementServerProperties);
80+
}
81+
}
82+
83+
@Configuration
84+
@ConditionalOnClass( {ServerProperties.class, EndpointsSupplier.class, ExposableWebEndpoint.class})
85+
@ConditionalOnBean(ServerProperties.class)
86+
@ConditionalOnProperty(value = "opentracing.spring.web.ignoreAutoConfiguredSkipPatterns", havingValue = "false", matchIfMissing = true)
87+
protected static class ActuatorSkipPatternProviderConfig {
88+
89+
static Optional<Pattern> getEndpointsPatterns(String contextPath,
90+
WebEndpointProperties webEndpointProperties,
91+
EndpointsSupplier<ExposableWebEndpoint> endpointsSupplier) {
92+
Collection<ExposableWebEndpoint> endpoints = endpointsSupplier.getEndpoints();
93+
94+
if (endpoints.isEmpty()) {
95+
return Optional.empty();
96+
}
97+
98+
String pattern = endpoints.stream().map(PathMappedEndpoint::getRootPath)
99+
.map(path -> path + "|" + path + "/.*").collect(
100+
Collectors.joining("|",
101+
getPathPrefix(contextPath,
102+
webEndpointProperties.getBasePath()) + "/(",
103+
")"));
104+
if (StringUtils.hasText(pattern)) {
105+
return Optional.of(Pattern.compile(pattern));
106+
}
107+
return Optional.empty();
108+
}
109+
110+
private static String getPathPrefix(String contextPath, String actuatorBasePath) {
111+
String result = "";
112+
if (StringUtils.hasText(contextPath)) {
113+
result += contextPath;
114+
}
115+
if (!actuatorBasePath.equals("/")) {
116+
result += actuatorBasePath;
117+
}
118+
return result;
119+
}
120+
121+
@Bean
122+
@ConditionalOnManagementPort(ManagementPortType.SAME)
123+
public SkipPattern skipPatternForActuatorEndpointsSamePort(
124+
final ServerProperties serverProperties,
125+
final WebEndpointProperties webEndpointProperties,
126+
final EndpointsSupplier<ExposableWebEndpoint> endpointsSupplier) {
127+
return () -> getEndpointsPatterns(
128+
serverProperties.getServlet().getContextPath(), webEndpointProperties,
129+
endpointsSupplier);
130+
}
131+
132+
@Bean
133+
@ConditionalOnManagementPort(ManagementPortType.DIFFERENT)
134+
@ConditionalOnProperty(name = "management.server.servlet.context-path", havingValue = "/", matchIfMissing = true)
135+
public SkipPattern skipPatternForActuatorEndpointsDifferentPort(
136+
final WebEndpointProperties webEndpointProperties,
137+
final EndpointsSupplier<ExposableWebEndpoint> endpointsSupplier) {
138+
return () -> getEndpointsPatterns(null, webEndpointProperties,
139+
endpointsSupplier);
140+
}
141+
}
142+
143+
@Configuration
144+
protected static class DefaultSkipPatternConfig {
145+
146+
private static String combinedPatterns(String skipPattern) {
147+
String pattern = skipPattern;
148+
if (!StringUtils.hasText(skipPattern)) {
149+
pattern = WebTracingProperties.DEFAULT_SKIP_PATTERN;
150+
}
151+
return pattern;
152+
}
153+
154+
@Bean
155+
SkipPattern defaultSkipPatternBean(WebTracingProperties webTracingProperties) {
156+
return () -> Optional.of(Pattern.compile(combinedPatterns(webTracingProperties.getSkipPattern())));
157+
}
158+
}
159+
160+
}

opentracing-spring-web-starter/src/main/java/io/opentracing/contrib/spring/web/starter/WebFluxTracingAutoConfiguration.java

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,11 @@
1313
*/
1414
package io.opentracing.contrib.spring.web.starter;
1515

16-
import io.opentracing.Tracer;
17-
import io.opentracing.contrib.spring.tracer.configuration.TracerAutoConfiguration;
18-
import io.opentracing.contrib.spring.web.webfilter.TracingWebFilter;
19-
import io.opentracing.contrib.spring.web.webfilter.WebFluxSpanDecorator;
16+
import java.util.List;
17+
import java.util.regex.Pattern;
18+
2019
import org.springframework.beans.factory.ObjectProvider;
20+
import org.springframework.beans.factory.annotation.Qualifier;
2121
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
2222
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
2323
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
@@ -27,20 +27,25 @@
2727
import org.springframework.context.annotation.Bean;
2828
import org.springframework.context.annotation.Configuration;
2929

30-
import java.util.List;
30+
import io.opentracing.Tracer;
31+
import io.opentracing.contrib.spring.tracer.configuration.TracerAutoConfiguration;
32+
import io.opentracing.contrib.spring.web.webfilter.TracingWebFilter;
33+
import io.opentracing.contrib.spring.web.webfilter.WebFluxSpanDecorator;
3134

3235
/**
3336
* Instrumentation of WebFlux.
3437
*
3538
* @author Csaba Kos
39+
* @author Gilles Robert
3640
*/
3741
@Configuration
3842
@ConditionalOnBean(Tracer.class)
39-
@AutoConfigureAfter(TracerAutoConfiguration.class)
43+
@AutoConfigureAfter({TracerAutoConfiguration.class, SkipPatternAutoConfiguration.class})
4044
@EnableConfigurationProperties(WebTracingProperties.class)
4145
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE)
4246
@ConditionalOnProperty(name = WebTracingProperties.CONFIGURATION_PREFIX + ".enabled", havingValue = "true", matchIfMissing = true)
4347
public class WebFluxTracingAutoConfiguration {
48+
4449
@ConditionalOnMissingBean(WebFluxSpanDecorator.class)
4550
@Configuration
4651
static class DefaultWebFluxSpanDecorators {
@@ -60,12 +65,13 @@ WebFluxSpanDecorator webFluxTagsWebFluxSpanDecorator() {
6065
public TracingWebFilter traceFilter(
6166
final Tracer tracer,
6267
final WebTracingProperties webTracingProperties,
63-
final ObjectProvider<List<WebFluxSpanDecorator>> webFilterSpanDecorators
68+
final ObjectProvider<List<WebFluxSpanDecorator>> webFilterSpanDecorators,
69+
final @Qualifier("skipPattern") Pattern skipPattern
6470
) {
6571
return new TracingWebFilter(
6672
tracer,
6773
webTracingProperties.getOrder(),
68-
webTracingProperties.getSkipPattern(),
74+
skipPattern,
6975
webTracingProperties.getUrlPatterns(),
7076
webFilterSpanDecorators.getObject()
7177
);

opentracing-spring-web-starter/src/main/java/io/opentracing/contrib/spring/web/starter/WebTracingProperties.java

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,25 +13,24 @@
1313
*/
1414
package io.opentracing.contrib.spring.web.starter;
1515

16-
import java.util.*;
17-
import java.util.regex.Pattern;
16+
import java.util.Collections;
17+
import java.util.List;
1818

1919
import org.springframework.boot.context.properties.ConfigurationProperties;
2020

2121
/**
2222
* @author Pavol Loffay
23+
* @author Gilles Robert
2324
*/
2425
@ConfigurationProperties(WebTracingProperties.CONFIGURATION_PREFIX)
2526
public class WebTracingProperties {
2627

2728
public static final String CONFIGURATION_PREFIX = "opentracing.spring.web";
2829

29-
public static final Pattern DEFAULT_SKIP_PATTERN = Pattern.compile(
30-
"/api-docs.*|/autoconfig|/configprops|/dump|/health|/info|/metrics.*|/actuator.*|" +
31-
"/mappings|/swagger.*|.*\\.png|.*\\.css|.*\\.js|.*\\.html|/favicon.ico|/hystrix.stream");
30+
static final String DEFAULT_SKIP_PATTERN = "/api-docs.*|/swagger.*|.*\\.png|.*\\.css|.*\\.js|.*\\.html|/favicon.ico|/hystrix.stream";
3231

3332
private boolean enabled = true;
34-
private Pattern skipPattern = DEFAULT_SKIP_PATTERN;
33+
private String skipPattern = DEFAULT_SKIP_PATTERN;
3534
private int order = Integer.MIN_VALUE;
3635

3736
/**
@@ -54,11 +53,11 @@ public void setEnabled(boolean enabled) {
5453
this.enabled = enabled;
5554
}
5655

57-
public Pattern getSkipPattern() {
56+
public String getSkipPattern() {
5857
return skipPattern;
5958
}
6059

61-
public void setSkipPattern(Pattern skipPattern) {
60+
public void setSkipPattern(String skipPattern) {
6261
this.skipPattern = skipPattern;
6362
}
6463

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
22
io.opentracing.contrib.spring.web.starter.ServerTracingAutoConfiguration,\
3+
io.opentracing.contrib.spring.web.starter.SkipPatternAutoConfiguration,\
34
io.opentracing.contrib.spring.web.starter.RestTemplateTracingAutoConfiguration,\
45
io.opentracing.contrib.spring.web.starter.WebClientTracingAutoConfiguration,\
56
io.opentracing.contrib.spring.web.starter.WebFluxTracingAutoConfiguration

opentracing-spring-web-starter/src/test/java/io/opentracing/contrib/spring/web/starter/CustomSpanDecoratorAutoConfigurationTest.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import org.hamcrest.core.IsEqual;
2323
import org.junit.Assert;
2424
import org.junit.Before;
25+
import org.junit.Ignore;
2526
import org.junit.Test;
2627
import org.junit.runner.RunWith;
2728
import org.springframework.beans.factory.annotation.Autowired;
@@ -174,6 +175,7 @@ public void testAsyncRestClientCustomTracing() {
174175
Assert.assertEquals("foo", mockTracer.finishedSpans().get(0).tags().get("custom-test"));
175176
}
176177

178+
@Ignore("Fix me, I'm flaky!")
177179
@Test
178180
public void testWebClientCustomTracing() {
179181
try {

0 commit comments

Comments
 (0)