Enhance endpoints handling (#1201)

* Enhance endpoints handling
* Add conditionalOnBean ServerProperties
* Code review remarks from @shakuzen
* Provide ignoreAutoConfiguredSkipPatterns flag.
* Update documentation related to spring boot actuator and new flag spring.sleuth.web.ignore-auto-configured-skip-patterns.
This commit is contained in:
Gilles Robert
2019-02-05 15:16:00 +01:00
committed by Marcin Grzejszczak
parent 1775ec1000
commit 5fb9177dec
10 changed files with 659 additions and 33 deletions

View File

@@ -1072,6 +1072,10 @@ You can configure which URIs you would like to skip by setting the `spring.sleut
If you have `ManagementServerProperties` on classpath, 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 by using the `spring.sleuth.web.additionalSkipPattern`.
By default, all the spring boot actuator endpoints are automatically added to the skip pattern.
If you want to disable this behaviour set `spring.sleuth.web.ignore-auto-configured-skip-patterns`
to `true`.
To change the order of tracing filter registration, please set the
`spring.sleuth.web.filter-order` property.

View File

@@ -31,7 +31,7 @@ public class SleuthWebProperties {
/**
* Default set of skip patterns.
*/
public static final String DEFAULT_SKIP_PATTERN = "/api-docs.*|/autoconfig|/configprops|/dump|/health|/info|/metrics.*|/mappings|/trace|/swagger.*|.*\\.png|.*\\.css|.*\\.js|.*\\.html|/favicon.ico|/hystrix.stream|/application/.*|/actuator.*|/cloudfoundryapplication";
public static final String DEFAULT_SKIP_PATTERN = "/api-docs.*|/swagger.*|.*\\.png|.*\\.css|.*\\.js|.*\\.html|/favicon.ico|/hystrix.stream";
/**
* When true enables instrumentation for web applications.
@@ -67,6 +67,12 @@ public class SleuthWebProperties {
*/
private boolean exceptionLoggingFilterEnabled = true;
/**
* If set to true, auto-configured skip patterns will be ignored.
* @see TraceWebAutoConfiguration
*/
private boolean ignoreAutoConfiguredSkipPatterns = false;
/**
* Properties related to HTTP clients.
*/
@@ -125,6 +131,15 @@ public class SleuthWebProperties {
this.exceptionLoggingFilterEnabled = exceptionLoggingFilterEnabled;
}
public boolean isIgnoreAutoConfiguredSkipPatterns() {
return ignoreAutoConfiguredSkipPatterns;
}
public void setIgnoreAutoConfiguredSkipPatterns(
boolean ignoreAutoConfiguredSkipPatterns) {
this.ignoreAutoConfiguredSkipPatterns = ignoreAutoConfiguredSkipPatterns;
}
public Client getClient() {
return this.client;
}

View File

@@ -16,6 +16,7 @@
package org.springframework.cloud.sleuth.instrument.web;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.regex.Pattern;
@@ -25,6 +26,9 @@ import brave.Tracing;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties;
import org.springframework.boot.actuate.autoconfigure.web.server.ManagementServerProperties;
import org.springframework.boot.actuate.endpoint.EndpointsSupplier;
import org.springframework.boot.actuate.endpoint.web.ExposableWebEndpoint;
import org.springframework.boot.actuate.endpoint.web.PathMappedEndpoint;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
@@ -66,6 +70,7 @@ public class TraceWebAutoConfiguration {
@Configuration
@ConditionalOnClass(ManagementServerProperties.class)
@ConditionalOnProperty(value = "spring.sleuth.web.ignoreAutoConfiguredSkipPatterns", havingValue = "false", matchIfMissing = true)
protected static class ManagementSkipPatternProviderConfig {
/**
@@ -93,31 +98,53 @@ public class TraceWebAutoConfiguration {
}
@Configuration
@ConditionalOnClass({ ServerProperties.class, WebEndpointProperties.class })
protected static class ServerSkipPatternProviderConfig {
@ConditionalOnClass({ ServerProperties.class, EndpointsSupplier.class,
ExposableWebEndpoint.class })
@ConditionalOnBean(ServerProperties.class)
@ConditionalOnProperty(value = "spring.sleuth.web.ignoreAutoConfiguredSkipPatterns", havingValue = "false", matchIfMissing = true)
protected static class ActuatorSkipPatternProviderConfig {
static Optional<Pattern> getEndpointsPatterns(ServerProperties serverProperties,
WebEndpointProperties webEndpointProperties,
EndpointsSupplier<ExposableWebEndpoint> endpointsSupplier) {
Collection<ExposableWebEndpoint> endpoints = endpointsSupplier.getEndpoints();
if (endpoints.isEmpty()) {
return Optional.empty();
}
/**
* Uses {@link ServerProperties#getServlet()#getContextPath()} and
* {@link WebEndpointProperties#getBasePath()} to skip Actuator endpoints.
*/
static Optional<Pattern> getPatternForServerProperties(
ServerProperties serverProperties,
WebEndpointProperties webEndpointProperties) {
String contextPath = serverProperties.getServlet().getContextPath();
if (StringUtils.hasText(contextPath)) {
return Optional.of(Pattern.compile(
contextPath + webEndpointProperties.getBasePath() + ".*"));
String pattern = endpoints.stream().map(PathMappedEndpoint::getRootPath)
.map(path -> path + "|" + path + "/.*").collect(
Collectors.joining("|",
getPathPrefix(contextPath,
webEndpointProperties.getBasePath()) + "/(",
")"));
if (StringUtils.hasText(pattern)) {
return Optional.of(Pattern.compile(pattern));
}
return Optional.empty();
}
private static String getPathPrefix(String contextPath, String actuatorBasePath) {
String result = "";
if (StringUtils.hasText(contextPath)) {
result += contextPath;
}
if (!actuatorBasePath.equals("/")) {
result += actuatorBasePath;
}
return result;
}
@Bean
@ConditionalOnBean({ ServerProperties.class, WebEndpointProperties.class })
public SingleSkipPattern skipPatternForServerProperties(
public SingleSkipPattern skipPatternForActuatorEndpoints(
final ServerProperties serverProperties,
final WebEndpointProperties webEndpointProperties) {
return () -> getPatternForServerProperties(serverProperties,
webEndpointProperties);
final WebEndpointProperties webEndpointProperties,
final EndpointsSupplier<ExposableWebEndpoint> endpointsSupplier) {
return () -> getEndpointsPatterns(serverProperties, webEndpointProperties,
endpointsSupplier);
}
}

View File

@@ -0,0 +1,121 @@
/*
* 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;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.cloud.sleuth.DisableSecurity;
import org.springframework.cloud.sleuth.util.ArrayListSpanReporter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import brave.Tracer;
import brave.sampler.Sampler;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.assertj.core.api.BDDAssertions.then;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = IgnoreAutoConfiguredSkipPatternsIntegrationTests.Config.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, properties = {
"management.endpoints.web.exposure.include:*",
"server.servlet.context-path:/context-path",
"spring.sleuth.http.legacy.enabled:true",
"spring.sleuth.web.ignoreAutoConfiguredSkipPatterns:true" })
public class IgnoreAutoConfiguredSkipPatternsIntegrationTests {
@Autowired
ArrayListSpanReporter accumulator;
@Autowired
Tracer tracer;
@LocalServerPort
int port;
@Before
@After
public void clearSpans() {
this.accumulator.clear();
}
@Test
public void should_sample_actuator_endpoint_when_override_pattern_is_true() {
new RestTemplate().getForObject(
"http://localhost:" + this.port + "/context-path/actuator/health",
String.class);
then(this.tracer.currentSpan()).isNull();
then(this.accumulator.getSpans()).hasSize(1);
}
@Test
public void should_sample_non_actuator_endpoint_when_override_pattern_is_true() {
new RestTemplate().getForObject(
"http://localhost:" + this.port + "/context-path/something",
String.class);
then(this.tracer.currentSpan()).isNull();
then(this.accumulator.getSpans()).hasSize(1);
}
@Test
public void should_not_sample_default_skip_patterns_when_override_pattern_is_true() {
new RestTemplate().getForObject(
"http://localhost:" + this.port + "/context-path/index.html",
String.class);
then(this.tracer.currentSpan()).isNull();
then(this.accumulator.getSpans()).hasSize(0);
}
@EnableAutoConfiguration(exclude = RabbitAutoConfiguration.class)
@Configuration
@DisableSecurity
@RestController
public static class Config {
@GetMapping("something")
void doNothing() {
}
@GetMapping("index.html")
void html() {
}
@Bean
ArrayListSpanReporter reporter() {
return new ArrayListSpanReporter();
}
@Bean
Sampler sampler() {
return Sampler.ALWAYS_SAMPLE;
}
}
}

View File

@@ -14,10 +14,12 @@
* limitations under the License.
*/
package org.springframework.cloud.sleuth.instrument.web.issues.issue971;
package org.springframework.cloud.sleuth.instrument.web;
import brave.Tracer;
import brave.sampler.Sampler;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
@@ -37,11 +39,11 @@ import org.springframework.web.client.RestTemplate;
import static org.assertj.core.api.BDDAssertions.then;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = DemoSleuthSkipApplicationTests.Config.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, properties = {
@SpringBootTest(classes = SkipEndPointsIntegrationTestsWithContextPathWithBasePath.Config.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, properties = {
"management.endpoints.web.exposure.include:*",
"server.servlet.context-path:/context-path",
"spring.sleuth.http.legacy.enabled:true" })
public class DemoSleuthSkipApplicationTests {
public class SkipEndPointsIntegrationTestsWithContextPathWithBasePath {
@Autowired
ArrayListSpanReporter accumulator;
@@ -52,6 +54,12 @@ public class DemoSleuthSkipApplicationTests {
@LocalServerPort
int port;
@Before
@After
public void clearSpans() {
this.accumulator.clear();
}
@Test
public void should_not_sample_skipped_endpoint_with_context_path() {
new RestTemplate().getForObject(

View File

@@ -0,0 +1,118 @@
package org.springframework.cloud.sleuth.instrument.web;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.cloud.sleuth.DisableSecurity;
import org.springframework.cloud.sleuth.util.ArrayListSpanReporter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import brave.Tracer;
import brave.sampler.Sampler;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.assertj.core.api.BDDAssertions.then;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = SkipEndPointsIntegrationTestsWithContextPathWithoutBasePath.Config.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, properties = {
"management.endpoints.web.exposure.include:*",
"server.servlet.context-path:/context-path",
"spring.sleuth.http.legacy.enabled:true",
"management.endpoints.web.base-path:/" })
public class SkipEndPointsIntegrationTestsWithContextPathWithoutBasePath {
@Autowired
private ArrayListSpanReporter spanReporter;
@Autowired
private Tracer tracer;
@LocalServerPort
int port;
@Before
@After
public void clearSpans() {
this.spanReporter.clear();
}
@Test
public void should_sample_non_actuator_endpoint_with_context_path() {
new RestTemplate().getForObject(
"http://localhost:" + this.port + "/context-path/something",
String.class);
then(this.tracer.currentSpan()).isNull();
then(this.spanReporter.getSpans()).hasSize(1);
}
@Test
public void should_sample_non_actuator_endpoint_with_context_path_and_health_in_path() {
new RestTemplate().getForObject(
"http://localhost:" + this.port + "/context-path/healthcare",
String.class);
then(this.tracer.currentSpan()).isNull();
then(this.spanReporter.getSpans()).hasSize(1);
}
@Test
public void should_not_sample_actuator_endpoint_with_base_path_set_to_root() {
new RestTemplate().getForObject(
"http://localhost:" + this.port + "/context-path/health", String.class);
then(this.tracer.currentSpan()).isNull();
then(this.spanReporter.getSpans()).hasSize(0);
}
@Test
public void should_not_sample_actuator_endpoint_with_base_path_set_to_root_and_parameter() {
new RestTemplate().getForObject(
"http://localhost:" + this.port + "/context-path/metrics?xyz",
String.class);
then(this.tracer.currentSpan()).isNull();
then(this.spanReporter.getSpans()).hasSize(0);
}
@EnableAutoConfiguration(exclude = RabbitAutoConfiguration.class)
@Configuration
@DisableSecurity
@RestController
public static class Config {
@GetMapping("something")
void doNothing() {
}
@GetMapping("healthcare")
void healthCare() {
}
@GetMapping("metrics")
void metrics() {
}
@Bean
ArrayListSpanReporter reporter() {
return new ArrayListSpanReporter();
}
@Bean
Sampler sampler() {
return Sampler.ALWAYS_SAMPLE;
}
}
}

View File

@@ -0,0 +1,113 @@
package org.springframework.cloud.sleuth.instrument.web;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.cloud.sleuth.DisableSecurity;
import org.springframework.cloud.sleuth.util.ArrayListSpanReporter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import brave.Tracer;
import brave.sampler.Sampler;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.assertj.core.api.BDDAssertions.then;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = SkipEndPointsIntegrationTestsWithoutContextPathWithBasePath.Config.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, properties = {
"management.endpoints.web.exposure.include:*",
"spring.sleuth.http.legacy.enabled:true" })
public class SkipEndPointsIntegrationTestsWithoutContextPathWithBasePath {
@Autowired
private ArrayListSpanReporter spanReporter;
@Autowired
private Tracer tracer;
@LocalServerPort
int port;
@Before
@After
public void clearSpans() {
this.spanReporter.clear();
}
@Test
public void should_sample_non_actuator_endpoint() {
new RestTemplate().getForObject("http://localhost:" + this.port + "/something",
String.class);
then(this.tracer.currentSpan()).isNull();
then(this.spanReporter.getSpans()).hasSize(1);
}
@Test
public void should_sample_non_actuator_endpoint_and_healthcare_in_path() {
new RestTemplate().getForObject("http://localhost:" + this.port + "/healthcare",
String.class);
then(this.tracer.currentSpan()).isNull();
then(this.spanReporter.getSpans()).hasSize(1);
}
@Test
public void should_not_sample_actuator_endpoint() {
new RestTemplate().getForObject(
"http://localhost:" + this.port + "/actuator/health", String.class);
then(this.tracer.currentSpan()).isNull();
then(this.spanReporter.getSpans()).hasSize(0);
}
@Test
public void should_not_sample_actuator_endpoint_with_parameter() {
new RestTemplate().getForObject(
"http://localhost:" + this.port + "/actuator/metrics?xyz", String.class);
then(this.tracer.currentSpan()).isNull();
then(this.spanReporter.getSpans()).hasSize(0);
}
@EnableAutoConfiguration(exclude = RabbitAutoConfiguration.class)
@Configuration
@DisableSecurity
@RestController
public static class Config {
@GetMapping("something")
void doNothing() {
}
@GetMapping("healthcare")
void healthCare() {
}
@GetMapping("metrics")
void metrics() {
}
@Bean
ArrayListSpanReporter reporter() {
return new ArrayListSpanReporter();
}
@Bean
Sampler sampler() {
return Sampler.ALWAYS_SAMPLE;
}
}
}

View File

@@ -0,0 +1,114 @@
package org.springframework.cloud.sleuth.instrument.web;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.cloud.sleuth.DisableSecurity;
import org.springframework.cloud.sleuth.util.ArrayListSpanReporter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import brave.Tracer;
import brave.sampler.Sampler;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.assertj.core.api.BDDAssertions.then;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = SkipEndPointsIntegrationTestsWithoutContextPathWithoutBasePath.Config.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, properties = {
"management.endpoints.web.exposure.include:*",
"spring.sleuth.http.legacy.enabled:true",
"management.endpoints.web.base-path:/" })
public class SkipEndPointsIntegrationTestsWithoutContextPathWithoutBasePath {
@Autowired
private ArrayListSpanReporter spanReporter;
@Autowired
private Tracer tracer;
@LocalServerPort
int port;
@Before
@After
public void clearSpans() {
this.spanReporter.clear();
}
@Test
public void should_sample_non_actuator_endpoint() {
new RestTemplate().getForObject("http://localhost:" + this.port + "/something",
String.class);
then(this.tracer.currentSpan()).isNull();
then(this.spanReporter.getSpans()).hasSize(1);
}
@Test
public void should_sample_non_actuator_endpoint_with_healthcare_in_path() {
new RestTemplate().getForObject("http://localhost:" + this.port + "/healthcare",
String.class);
then(this.tracer.currentSpan()).isNull();
then(this.spanReporter.getSpans()).hasSize(1);
}
@Test
public void should_not_sample_actuator_endpoint() {
new RestTemplate().getForObject("http://localhost:" + this.port + "/health",
String.class);
then(this.tracer.currentSpan()).isNull();
then(this.spanReporter.getSpans()).hasSize(0);
}
@Test
public void should_not_sample_actuator_endpoint_with_parameter() {
new RestTemplate().getForObject("http://localhost:" + this.port + "/metrics?xyz",
String.class);
then(this.tracer.currentSpan()).isNull();
then(this.spanReporter.getSpans()).hasSize(0);
}
@EnableAutoConfiguration(exclude = RabbitAutoConfiguration.class)
@Configuration
@DisableSecurity
@RestController
public static class Config {
@GetMapping("something")
void doNothing() {
}
@GetMapping("healthcare")
void healthCare() {
}
@GetMapping("metrics")
void metrics() {
}
@Bean
ArrayListSpanReporter reporter() {
return new ArrayListSpanReporter();
}
@Bean
Sampler sampler() {
return Sampler.ALWAYS_SAMPLE;
}
}
}

View File

@@ -17,6 +17,8 @@
package org.springframework.cloud.sleuth.instrument.web;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Optional;
import java.util.regex.Pattern;
@@ -24,6 +26,10 @@ import org.junit.Test;
import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties;
import org.springframework.boot.actuate.autoconfigure.web.server.ManagementServerProperties;
import org.springframework.boot.actuate.endpoint.EndpointId;
import org.springframework.boot.actuate.endpoint.EndpointsSupplier;
import org.springframework.boot.actuate.endpoint.web.ExposableWebEndpoint;
import org.springframework.boot.actuate.endpoint.web.WebOperation;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import static org.assertj.core.api.BDDAssertions.then;
@@ -79,27 +85,103 @@ public class SkipPatternProviderConfigTest {
}
@Test
public void should_return_empty_when_server_props_have_no_context_path()
throws Exception {
Optional<Pattern> pattern = new TraceWebAutoConfiguration.ServerSkipPatternProviderConfig()
.skipPatternForServerProperties(new ServerProperties(),
new WebEndpointProperties())
public void should_return_empty_when_no_endpoints() {
EndpointsSupplier<ExposableWebEndpoint> endpointsSupplier = Collections::emptyList;
Optional<Pattern> pattern = new TraceWebAutoConfiguration.ActuatorSkipPatternProviderConfig()
.skipPatternForActuatorEndpoints(new ServerProperties(),
new WebEndpointProperties(), endpointsSupplier)
.skipPattern();
then(pattern).isEmpty();
}
@Test
public void should_return_server_props_with_context_path() throws Exception {
public void should_return_endpoints_without_context_path() {
ServerProperties properties = new ServerProperties();
properties.getServlet().setContextPath("foo");
WebEndpointProperties webEndpointProperties = new WebEndpointProperties();
EndpointsSupplier<ExposableWebEndpoint> endpointsSupplier = () -> {
ExposableWebEndpoint infoEndpoint = createEndpoint("info");
ExposableWebEndpoint healthEndpoint = createEndpoint("health");
Optional<Pattern> pattern = new TraceWebAutoConfiguration.ServerSkipPatternProviderConfig()
.skipPatternForServerProperties(properties, new WebEndpointProperties())
return Arrays.asList(infoEndpoint, healthEndpoint);
};
Optional<Pattern> pattern = new TraceWebAutoConfiguration.ActuatorSkipPatternProviderConfig()
.skipPatternForActuatorEndpoints(properties, webEndpointProperties,
endpointsSupplier)
.skipPattern();
then(pattern).isNotEmpty();
then(pattern.get().pattern()).isEqualTo("foo/actuator.*");
then(pattern.get().pattern())
.isEqualTo("/actuator/(info|info/.*|health|health/.*)");
}
@Test
public void should_return_endpoints_with_context_path() {
WebEndpointProperties webEndpointProperties = new WebEndpointProperties();
ServerProperties properties = new ServerProperties();
properties.getServlet().setContextPath("foo");
EndpointsSupplier<ExposableWebEndpoint> endpointsSupplier = () -> {
ExposableWebEndpoint infoEndpoint = createEndpoint("info");
ExposableWebEndpoint healthEndpoint = createEndpoint("health");
return Arrays.asList(infoEndpoint, healthEndpoint);
};
Optional<Pattern> pattern = new TraceWebAutoConfiguration.ActuatorSkipPatternProviderConfig()
.skipPatternForActuatorEndpoints(properties, webEndpointProperties,
endpointsSupplier)
.skipPattern();
then(pattern).isNotEmpty();
then(pattern.get().pattern())
.isEqualTo("foo/actuator/(info|info/.*|health|health/.*)");
}
@Test
public void should_return_endpoints_without_context_path_and_base_path_set_to_root() {
ServerProperties properties = new ServerProperties();
WebEndpointProperties webEndpointProperties = new WebEndpointProperties();
webEndpointProperties.setBasePath("/");
EndpointsSupplier<ExposableWebEndpoint> endpointsSupplier = () -> {
ExposableWebEndpoint infoEndpoint = createEndpoint("info");
ExposableWebEndpoint healthEndpoint = createEndpoint("health");
return Arrays.asList(infoEndpoint, healthEndpoint);
};
Optional<Pattern> pattern = new TraceWebAutoConfiguration.ActuatorSkipPatternProviderConfig()
.skipPatternForActuatorEndpoints(properties, webEndpointProperties,
endpointsSupplier)
.skipPattern();
then(pattern).isNotEmpty();
then(pattern.get().pattern()).isEqualTo("/(info|info/.*|health|health/.*)");
}
@Test
public void should_return_endpoints_with_context_path_and_base_path_set_to_root() {
WebEndpointProperties webEndpointProperties = new WebEndpointProperties();
webEndpointProperties.setBasePath("/");
ServerProperties properties = new ServerProperties();
properties.getServlet().setContextPath("foo");
EndpointsSupplier<ExposableWebEndpoint> endpointsSupplier = () -> {
ExposableWebEndpoint infoEndpoint = createEndpoint("info");
ExposableWebEndpoint healthEndpoint = createEndpoint("health");
return Arrays.asList(infoEndpoint, healthEndpoint);
};
Optional<Pattern> pattern = new TraceWebAutoConfiguration.ActuatorSkipPatternProviderConfig()
.skipPatternForActuatorEndpoints(properties, webEndpointProperties,
endpointsSupplier)
.skipPattern();
then(pattern).isNotEmpty();
then(pattern.get().pattern()).isEqualTo("foo/(info|info/.*|health|health/.*)");
}
@Test
@@ -120,4 +202,29 @@ public class SkipPatternProviderConfigTest {
return () -> Optional.of(Pattern.compile("bar"));
}
private ExposableWebEndpoint createEndpoint(final String name) {
return new ExposableWebEndpoint() {
@Override
public String getRootPath() {
return name;
}
@Override
public EndpointId getEndpointId() {
return EndpointId.of(name);
}
@Override
public boolean isEnableByDefault() {
return false;
}
@Override
public Collection<WebOperation> getOperations() {
return null;
}
};
}
}

View File

@@ -48,8 +48,7 @@ public class TraceRequestHttpHeadersFilterTests {
.isEqualTo(Collections.singletonList("World"));
BDDAssertions.then(filteredHeaders.get("X-Hello-Request"))
.isEqualTo(Collections.singletonList("Request World"));
BDDAssertions.then(filteredHeaders.get("X-Auth-User"))
.hasSize(1);
BDDAssertions.then(filteredHeaders.get("X-Auth-User")).hasSize(1);
BDDAssertions
.then((Object) exchange
.getAttribute(TraceRequestHttpHeadersFilter.SPAN_ATTRIBUTE))