diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/trace/http/HttpTraceAutoConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/trace/http/HttpTraceAutoConfiguration.java index d2f6e37b6c05..97c2e4e70b6f 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/trace/http/HttpTraceAutoConfiguration.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/trace/http/HttpTraceAutoConfiguration.java @@ -18,10 +18,10 @@ import org.springframework.boot.actuate.trace.http.HttpExchangeTracer; import org.springframework.boot.actuate.trace.http.HttpTraceRepository; -import org.springframework.boot.actuate.trace.http.InMemoryHttpTraceRepository; import org.springframework.boot.actuate.web.trace.reactive.HttpTraceWebFilter; import org.springframework.boot.actuate.web.trace.servlet.HttpTraceFilter; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; @@ -40,15 +40,10 @@ @ConditionalOnWebApplication @ConditionalOnProperty(prefix = "management.trace.http", name = "enabled", matchIfMissing = true) +@ConditionalOnBean(HttpTraceRepository.class) @EnableConfigurationProperties(HttpTraceProperties.class) public class HttpTraceAutoConfiguration { - @Bean - @ConditionalOnMissingBean(HttpTraceRepository.class) - public InMemoryHttpTraceRepository traceRepository() { - return new InMemoryHttpTraceRepository(); - } - @Bean @ConditionalOnMissingBean public HttpExchangeTracer httpExchangeTracer(HttpTraceProperties traceProperties) { diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/web/trace/HttpTraceAutoConfigurationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/web/trace/HttpTraceAutoConfigurationTests.java index be188f798bc5..9e5613c40990 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/web/trace/HttpTraceAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/web/trace/HttpTraceAutoConfigurationTests.java @@ -42,45 +42,34 @@ * Tests for {@link HttpTraceAutoConfiguration}. * * @author Andy Wilkinson + * @author Madhura Bhave */ public class HttpTraceAutoConfigurationTests { + private WebApplicationContextRunner contextRunner = new WebApplicationContextRunner() + .withConfiguration(AutoConfigurations.of(HttpTraceAutoConfiguration.class)); + @Test - public void configuresRepository() { - new WebApplicationContextRunner() - .withConfiguration( - AutoConfigurations.of(HttpTraceAutoConfiguration.class)) - .run((context) -> assertThat(context) - .hasSingleBean(InMemoryHttpTraceRepository.class)); + public void autoConfigurationIsDisabledByDefault() { + this.contextRunner.run((context) -> assertThat(context) + .doesNotHaveBean(HttpTraceAutoConfiguration.class)); } @Test - public void usesUserProvidedRepository() { - new WebApplicationContextRunner() - .withConfiguration( - AutoConfigurations.of(HttpTraceAutoConfiguration.class)) - .withUserConfiguration(CustomRepositoryConfiguration.class) + public void autoConfigurationIsEnabledWhenHttpTraceRepositoryBeanPresent() { + this.contextRunner.withUserConfiguration(HttpTraceRepositoryConfiguration.class) .run((context) -> { + assertThat(context).hasSingleBean(HttpExchangeTracer.class); + assertThat(context).hasSingleBean(HttpTraceFilter.class); assertThat(context).hasSingleBean(HttpTraceRepository.class); assertThat(context.getBean(HttpTraceRepository.class)) .isInstanceOf(CustomHttpTraceRepository.class); }); } - @Test - public void configuresTracer() { - new WebApplicationContextRunner() - .withConfiguration( - AutoConfigurations.of(HttpTraceAutoConfiguration.class)) - .run((context) -> assertThat(context) - .hasSingleBean(HttpExchangeTracer.class)); - } - @Test public void usesUserProvidedTracer() { - new WebApplicationContextRunner() - .withConfiguration( - AutoConfigurations.of(HttpTraceAutoConfiguration.class)) + this.contextRunner.withUserConfiguration(HttpTraceRepositoryConfiguration.class) .withUserConfiguration(CustomTracerConfiguration.class).run((context) -> { assertThat(context).hasSingleBean(HttpExchangeTracer.class); assertThat(context.getBean(HttpExchangeTracer.class)) @@ -89,19 +78,11 @@ public void usesUserProvidedTracer() { } @Test - public void configuresWebFilter() { - new ReactiveWebApplicationContextRunner() - .withConfiguration( - AutoConfigurations.of(HttpTraceAutoConfiguration.class)) - .run((context) -> assertThat(context) - .hasSingleBean(HttpTraceWebFilter.class)); - } - - @Test - public void usesUserProvidedWebFilter() { + public void usesUserProvidedWebFilterWhenReactiveContext() { new ReactiveWebApplicationContextRunner() .withConfiguration( AutoConfigurations.of(HttpTraceAutoConfiguration.class)) + .withUserConfiguration(HttpTraceRepositoryConfiguration.class) .withUserConfiguration(CustomWebFilterConfiguration.class) .run((context) -> { assertThat(context).hasSingleBean(HttpTraceWebFilter.class); @@ -110,20 +91,9 @@ public void usesUserProvidedWebFilter() { }); } - @Test - public void configuresServletFilter() { - new WebApplicationContextRunner() - .withConfiguration( - AutoConfigurations.of(HttpTraceAutoConfiguration.class)) - .run((context) -> assertThat(context) - .hasSingleBean(HttpTraceFilter.class)); - } - @Test public void usesUserProvidedServletFilter() { - new WebApplicationContextRunner() - .withConfiguration( - AutoConfigurations.of(HttpTraceAutoConfiguration.class)) + this.contextRunner.withUserConfiguration(HttpTraceRepositoryConfiguration.class) .withUserConfiguration(CustomFilterConfiguration.class).run((context) -> { assertThat(context).hasSingleBean(HttpTraceFilter.class); assertThat(context.getBean(HttpTraceFilter.class)) @@ -133,9 +103,7 @@ public void usesUserProvidedServletFilter() { @Test public void backsOffWhenDisabled() { - new WebApplicationContextRunner() - .withConfiguration( - AutoConfigurations.of(HttpTraceAutoConfiguration.class)) + this.contextRunner.withUserConfiguration(HttpTraceRepositoryConfiguration.class) .withPropertyValues("management.trace.http.enabled=false") .run((context) -> assertThat(context) .doesNotHaveBean(InMemoryHttpTraceRepository.class) @@ -158,7 +126,7 @@ public void add(HttpTrace trace) { } @Configuration(proxyBeanMethods = false) - static class CustomRepositoryConfiguration { + static class HttpTraceRepositoryConfiguration { @Bean public CustomHttpTraceRepository customRepository() { diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/web/trace/HttpTraceEndpointAutoConfigurationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/web/trace/HttpTraceEndpointAutoConfigurationTests.java index ec8f56429aa2..d5a2e67c75de 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/web/trace/HttpTraceEndpointAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/web/trace/HttpTraceEndpointAutoConfigurationTests.java @@ -21,8 +21,11 @@ import org.springframework.boot.actuate.autoconfigure.trace.http.HttpTraceAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.trace.http.HttpTraceEndpointAutoConfiguration; import org.springframework.boot.actuate.trace.http.HttpTraceEndpoint; +import org.springframework.boot.actuate.trace.http.InMemoryHttpTraceRepository; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.test.context.runner.WebApplicationContextRunner; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; import static org.assertj.core.api.Assertions.assertThat; @@ -30,6 +33,7 @@ * Tests for {@link HttpTraceEndpointAutoConfiguration}. * * @author Phillip Webb + * @author Madhura Bhave */ public class HttpTraceEndpointAutoConfigurationTests { @@ -38,8 +42,8 @@ public class HttpTraceEndpointAutoConfigurationTests { HttpTraceEndpointAutoConfiguration.class)); @Test - public void runShouldHaveEndpointBean() { - this.contextRunner + public void runWhenRepositoryBeanAvailableShouldHaveEndpointBean() { + this.contextRunner.withUserConfiguration(HttpTraceRepositoryConfiguration.class) .withPropertyValues("management.endpoints.web.exposure.include=httptrace") .run((context) -> assertThat(context) .hasSingleBean(HttpTraceEndpoint.class)); @@ -47,13 +51,15 @@ public void runShouldHaveEndpointBean() { @Test public void runWhenNotExposedShouldNotHaveEndpointBean() { - this.contextRunner.run((context) -> assertThat(context) - .doesNotHaveBean(HttpTraceEndpoint.class)); + this.contextRunner.withUserConfiguration(HttpTraceRepositoryConfiguration.class) + .run((context) -> assertThat(context) + .doesNotHaveBean(HttpTraceEndpoint.class)); } @Test public void runWhenEnabledPropertyIsFalseShouldNotHaveEndpointBean() { - this.contextRunner + this.contextRunner.withUserConfiguration(HttpTraceRepositoryConfiguration.class) + .withPropertyValues("management.endpoints.web.exposure.include=httptrace") .withPropertyValues("management.endpoint.httptrace.enabled:false") .run((context) -> assertThat(context) .doesNotHaveBean(HttpTraceEndpoint.class)); @@ -61,9 +67,20 @@ public void runWhenEnabledPropertyIsFalseShouldNotHaveEndpointBean() { @Test public void endpointBacksOffWhenRepositoryIsNotAvailable() { - this.contextRunner.withPropertyValues("management.trace.http.enabled:false") + this.contextRunner + .withPropertyValues("management.endpoints.web.exposure.include=httptrace") .run((context) -> assertThat(context) .doesNotHaveBean(HttpTraceEndpoint.class)); } + @Configuration(proxyBeanMethods = false) + static class HttpTraceRepositoryConfiguration { + + @Bean + public InMemoryHttpTraceRepository customRepository() { + return new InMemoryHttpTraceRepository(); + } + + } + } diff --git a/spring-boot-project/spring-boot-docs/src/main/asciidoc/production-ready-features.adoc b/spring-boot-project/spring-boot-docs/src/main/asciidoc/production-ready-features.adoc index 3b310afbf8e8..410566dbc3b9 100644 --- a/spring-boot-project/spring-boot-docs/src/main/asciidoc/production-ready-features.adoc +++ b/spring-boot-project/spring-boot-docs/src/main/asciidoc/production-ready-features.adoc @@ -2213,8 +2213,12 @@ implementing `ApplicationEventPublisherAware`). [[production-ready-http-tracing]] == HTTP Tracing -Tracing is automatically enabled for all HTTP requests. You can view the `httptrace` -endpoint and obtain basic information about the last 100 request-response exchanges. +HTTP Tracing can be enabled by providing a bean of type `HttpTraceRepository` in your application's +configuration. For convenience, Spring Boot offers an `InMemoryHttpTraceRepository` that stores traces +for the last 100 request-response exchanges, by default. `InMemoryHttpTraceRepository` is limited +compared to other tracing solutions and we recommend using it only for development environments. +For production environments, consider creating your own alternative `HttpTraceRepository` implementation. +You can view the `httptrace` endpoint and obtain information about the request-response exchanges. @@ -2224,11 +2228,6 @@ To customize the items that are included in each trace, use the `management.trace.http.include` configuration property. For advanced customization, consider registering your own `HttpExchangeTracer` implementation. -By default, an `InMemoryHttpTraceRepository` that stores traces for the last 100 -request-response exchanges is used. If you need to expand the capacity, you can define -your own instance of the `InMemoryHttpTraceRepository` bean. You can also create your own -alternative `HttpTraceRepository` implementation. - [[production-ready-process-monitoring]]