Skip to content

Commit 4c37686

Browse files
committed
Move HTTP client observation support into relevant modules
1 parent 25c755a commit 4c37686

File tree

31 files changed

+251
-249
lines changed

31 files changed

+251
-249
lines changed

spring-boot-project/spring-boot-actuator-autoconfigure-all/src/main/java/org/springframework/boot/actuate/autoconfigure/observation/web/client/HttpClientObservationsAutoConfiguration.java

Lines changed: 0 additions & 82 deletions
This file was deleted.

spring-boot-project/spring-boot-actuator-autoconfigure-all/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ org.springframework.boot.actuate.autoconfigure.management.ThreadDumpEndpointAuto
1616
org.springframework.boot.actuate.autoconfigure.metrics.data.RepositoryMetricsAutoConfiguration
1717
org.springframework.boot.actuate.autoconfigure.metrics.task.TaskExecutorMetricsAutoConfiguration
1818
org.springframework.boot.actuate.autoconfigure.observability.ObservabilityAutoConfiguration
19-
org.springframework.boot.actuate.autoconfigure.observation.web.client.HttpClientObservationsAutoConfiguration
2019
org.springframework.boot.actuate.autoconfigure.observation.web.reactive.WebFluxObservationAutoConfiguration
2120
org.springframework.boot.actuate.autoconfigure.observation.web.servlet.WebMvcObservationAutoConfiguration
2221
org.springframework.boot.actuate.autoconfigure.r2dbc.ConnectionFactoryHealthContributorAutoConfiguration

spring-boot-project/spring-boot-actuator-autoconfigure-all/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/test/MetricsIntegrationTests.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@
3535

3636
import org.springframework.beans.factory.annotation.Autowired;
3737
import org.springframework.boot.actuate.autoconfigure.observability.ObservabilityAutoConfiguration;
38-
import org.springframework.boot.actuate.autoconfigure.observation.web.client.HttpClientObservationsAutoConfiguration;
3938
import org.springframework.boot.actuate.autoconfigure.observation.web.reactive.WebFluxObservationAutoConfiguration;
4039
import org.springframework.boot.actuate.autoconfigure.observation.web.servlet.WebMvcObservationAutoConfiguration;
4140
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
@@ -50,6 +49,7 @@
5049
import org.springframework.boot.micrometer.observation.autoconfigure.ObservationAutoConfiguration;
5150
import org.springframework.boot.restclient.RestTemplateBuilder;
5251
import org.springframework.boot.restclient.autoconfigure.RestTemplateAutoConfiguration;
52+
import org.springframework.boot.restclient.autoconfigure.observation.RestTemplateObservationAutoConfiguration;
5353
import org.springframework.boot.test.context.SpringBootTest;
5454
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
5555
import org.springframework.boot.tomcat.autoconfigure.servlet.TomcatServletWebServerAutoConfiguration;
@@ -147,7 +147,7 @@ void metricsFilterRegisteredForAsyncDispatches() {
147147
ObservabilityAutoConfiguration.class, JvmMetricsAutoConfiguration.class,
148148
LogbackMetricsAutoConfiguration.class, SystemMetricsAutoConfiguration.class,
149149
DataSourcePoolMetricsAutoConfiguration.class, HibernateMetricsAutoConfiguration.class,
150-
HttpClientObservationsAutoConfiguration.class, WebFluxObservationAutoConfiguration.class,
150+
RestTemplateObservationAutoConfiguration.class, WebFluxObservationAutoConfiguration.class,
151151
WebMvcObservationAutoConfiguration.class, JacksonAutoConfiguration.class,
152152
HttpMessageConvertersAutoConfiguration.class, RestTemplateAutoConfiguration.class,
153153
WebMvcAutoConfiguration.class, DispatcherServletAutoConfiguration.class,

spring-boot-project/spring-boot-actuator-autoconfigure-all/src/test/java/org/springframework/boot/actuate/autoconfigure/tracing/zipkin/ZipkinAutoConfigurationIntegrationTests.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,14 @@
1818

1919
import org.junit.jupiter.api.Test;
2020

21-
import org.springframework.boot.actuate.autoconfigure.observation.web.client.HttpClientObservationsAutoConfiguration;
2221
import org.springframework.boot.actuate.autoconfigure.tracing.BraveAutoConfiguration;
2322
import org.springframework.boot.actuate.autoconfigure.tracing.MicrometerTracingAutoConfiguration;
2423
import org.springframework.boot.autoconfigure.AutoConfigurations;
2524
import org.springframework.boot.metrics.autoconfigure.MetricsAutoConfiguration;
2625
import org.springframework.boot.metrics.autoconfigure.export.simple.SimpleMetricsExportAutoConfiguration;
2726
import org.springframework.boot.micrometer.observation.autoconfigure.ObservationAutoConfiguration;
2827
import org.springframework.boot.restclient.autoconfigure.RestTemplateAutoConfiguration;
28+
import org.springframework.boot.restclient.autoconfigure.observation.RestClientObservationAutoConfiguration;
2929
import org.springframework.boot.test.context.assertj.ApplicationContextAssertProvider;
3030
import org.springframework.boot.test.context.runner.AbstractApplicationContextRunner;
3131
import org.springframework.boot.test.context.runner.ReactiveWebApplicationContextRunner;
@@ -62,7 +62,7 @@ <SELF extends AbstractApplicationContextRunner<SELF, C, A>, C extends Configurab
6262
AbstractApplicationContextRunner<SELF, ?, ?> runner) {
6363
return runner.withConfiguration(AutoConfigurations.of(MicrometerTracingAutoConfiguration.class,
6464
ObservationAutoConfiguration.class, BraveAutoConfiguration.class, ZipkinAutoConfiguration.class,
65-
HttpClientObservationsAutoConfiguration.class, MetricsAutoConfiguration.class,
65+
RestClientObservationAutoConfiguration.class, MetricsAutoConfiguration.class,
6666
SimpleMetricsExportAutoConfiguration.class));
6767
}
6868

spring-boot-project/spring-boot-http-client/build.gradle

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ dependencies {
1313
api("org.springframework:spring-web")
1414

1515
optional(project(":spring-boot-project:spring-boot-autoconfigure"))
16+
optional(project(":spring-boot-project:spring-boot-metrics"))
1617
optional(project(":spring-boot-project:spring-boot-reactor-netty"))
1718
optional("org.apache.httpcomponents.client5:httpclient5")
1819
optional("org.apache.httpcomponents.core5:httpcore5-reactive")
@@ -23,6 +24,7 @@ dependencies {
2324
testImplementation(project(":spring-boot-project:spring-boot-tomcat"))
2425
testImplementation(project(":spring-boot-project:spring-boot-tools:spring-boot-test-support"))
2526
testImplementation("org.springframework:spring-webflux")
27+
testImplementation("io.micrometer:micrometer-observation-test")
2628

2729
testRuntimeOnly("ch.qos.logback:logback-classic")
2830
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/*
2+
* Copyright 2012-2025 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.http.client.autoconfigure.metrics;
18+
19+
import io.micrometer.core.instrument.MeterRegistry;
20+
import io.micrometer.core.instrument.config.MeterFilter;
21+
22+
import org.springframework.boot.autoconfigure.AutoConfiguration;
23+
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
24+
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
25+
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
26+
import org.springframework.boot.context.properties.EnableConfigurationProperties;
27+
import org.springframework.boot.metrics.OnlyOnceLoggingDenyMeterFilter;
28+
import org.springframework.boot.metrics.autoconfigure.MetricsProperties;
29+
import org.springframework.boot.metrics.autoconfigure.MetricsProperties.Web.Client;
30+
import org.springframework.boot.micrometer.observation.autoconfigure.ObservationProperties;
31+
import org.springframework.context.annotation.Bean;
32+
import org.springframework.core.annotation.Order;
33+
34+
/**
35+
* {@link EnableAutoConfiguration Auto-configuration} for HTTP client-related metrics.
36+
*
37+
* @author Jon Schneider
38+
* @author Phillip Webb
39+
* @author Stephane Nicoll
40+
* @author Raheela Aslam
41+
* @author Brian Clozel
42+
* @author Moritz Halbritter
43+
* @since 4.0.0
44+
*/
45+
@AutoConfiguration(afterName = "org.springframework.boot.metrics.autoconfigure.CompositeMeterRegistryAutoConfiguration")
46+
@ConditionalOnClass({ ObservationProperties.class, MeterRegistry.class, MetricsProperties.class })
47+
@ConditionalOnBean(MeterRegistry.class)
48+
@EnableConfigurationProperties({ MetricsProperties.class, ObservationProperties.class })
49+
public class HttpClientMetricsAutoConfiguration {
50+
51+
@Bean
52+
@Order(0)
53+
MeterFilter metricsHttpClientUriTagFilter(ObservationProperties observationProperties,
54+
MetricsProperties metricsProperties) {
55+
Client clientProperties = metricsProperties.getWeb().getClient();
56+
String name = observationProperties.getHttp().getClient().getRequests().getName();
57+
MeterFilter denyFilter = new OnlyOnceLoggingDenyMeterFilter(
58+
() -> "Reached the maximum number of URI tags for '%s'. Are you using 'uriVariables'?".formatted(name));
59+
return MeterFilter.maximumAllowableTags(name, "uri", clientProperties.getMaxUriTags(), denyFilter);
60+
}
61+
62+
}
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,6 @@
1515
*/
1616

1717
/**
18-
* Auto-configuration for web client observation support.
18+
* Auto-configuration for client-side HTTP metrics.
1919
*/
20-
package org.springframework.boot.actuate.autoconfigure.observation.web.client;
20+
package org.springframework.boot.http.client.autoconfigure.metrics;
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
org.springframework.boot.http.client.autoconfigure.HttpClientAutoConfiguration
2+
org.springframework.boot.http.client.autoconfigure.metrics.HttpClientMetricsAutoConfiguration
23
org.springframework.boot.http.client.reactive.autoconfigure.ClientHttpConnectorAutoConfiguration
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/*
2+
* Copyright 2012-2025 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.http.client.autoconfigure.metrics;
18+
19+
import java.time.Duration;
20+
21+
import io.micrometer.core.instrument.MeterRegistry;
22+
import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
23+
import org.junit.jupiter.api.Test;
24+
import org.junit.jupiter.api.extension.ExtendWith;
25+
26+
import org.springframework.boot.autoconfigure.AutoConfigurations;
27+
import org.springframework.boot.metrics.autoconfigure.MetricsAutoConfiguration;
28+
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
29+
import org.springframework.boot.test.system.CapturedOutput;
30+
import org.springframework.boot.test.system.OutputCaptureExtension;
31+
32+
import static org.assertj.core.api.Assertions.assertThat;
33+
34+
/**
35+
* Tests for {@link HttpClientMetricsAutoConfiguration}.
36+
*
37+
* @author Andy Wilkinson
38+
*/
39+
@ExtendWith(OutputCaptureExtension.class)
40+
class HttpClientMetricsAutoConfigurationTests {
41+
42+
@Test
43+
void afterMaxUrisReachedFurtherUrisAreDenied(CapturedOutput output) {
44+
new ApplicationContextRunner()
45+
.withConfiguration(
46+
AutoConfigurations.of(HttpClientMetricsAutoConfiguration.class, MetricsAutoConfiguration.class))
47+
.withBean(SimpleMeterRegistry.class)
48+
.withPropertyValues("management.metrics.web.client.max-uri-tags=2")
49+
.run((context) -> {
50+
MeterRegistry meterRegistry = context.getBean(MeterRegistry.class);
51+
for (int i = 0; i < 3; i++) {
52+
meterRegistry.timer("http.client.requests", "uri", "/test/" + i).record(Duration.ofSeconds(1));
53+
}
54+
assertThat(meterRegistry.find("http.client.requests").timers()).hasSize(2);
55+
assertThat(output).contains("Reached the maximum number of URI tags for 'http.client.requests'.")
56+
.contains("Are you using 'uriVariables'?");
57+
});
58+
}
59+
60+
}

spring-boot-project/spring-boot-restclient/build.gradle

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,12 @@ dependencies {
1414
implementation(project(":spring-boot-project:spring-boot-http-converter"))
1515

1616
optional(project(":spring-boot-project:spring-boot-autoconfigure"))
17+
optional(project(":spring-boot-project:spring-boot-micrometer-observation"))
1718
optional("io.projectreactor.netty:reactor-netty-http")
1819
optional("org.apache.httpcomponents.client5:httpclient5")
1920
optional("org.eclipse.jetty:jetty-client")
2021

22+
testImplementation(project(":spring-boot-project:spring-boot-metrics"))
2123
testImplementation(project(":spring-boot-project:spring-boot-test"))
2224
testImplementation(project(":spring-boot-project:spring-boot-tomcat"))
2325
testImplementation(project(":spring-boot-project:spring-boot-tools:spring-boot-test-support"))
Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,17 @@
1414
* limitations under the License.
1515
*/
1616

17-
package org.springframework.boot.actuate.autoconfigure.observation.web.client;
17+
package org.springframework.boot.restclient.autoconfigure.observation;
1818

1919
import io.micrometer.observation.ObservationRegistry;
2020

2121
import org.springframework.beans.factory.ObjectProvider;
2222
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
2323
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
24+
import org.springframework.boot.context.properties.EnableConfigurationProperties;
2425
import org.springframework.boot.micrometer.observation.autoconfigure.ObservationProperties;
2526
import org.springframework.boot.restclient.RestClientCustomizer;
26-
import org.springframework.boot.restclient.actuate.observation.ObservationRestClientCustomizer;
27+
import org.springframework.boot.restclient.observation.ObservationRestClientCustomizer;
2728
import org.springframework.context.annotation.Bean;
2829
import org.springframework.context.annotation.Configuration;
2930
import org.springframework.http.client.observation.ClientRequestObservationConvention;
@@ -34,11 +35,14 @@
3435
* Configure the instrumentation of {@link RestClient}.
3536
*
3637
* @author Moritz Halbritter
38+
* @since 4.0.0
3739
*/
3840
@Configuration(proxyBeanMethods = false)
39-
@ConditionalOnClass({ RestClient.class, ObservationRestClientCustomizer.class })
40-
@ConditionalOnBean(RestClient.Builder.class)
41-
class RestClientObservationConfiguration {
41+
@ConditionalOnClass({ RestClient.class, ObservationRestClientCustomizer.class, ObservationRegistry.class,
42+
ObservationProperties.class })
43+
@ConditionalOnBean({ RestClient.Builder.class, ObservationRegistry.class })
44+
@EnableConfigurationProperties(ObservationProperties.class)
45+
public class RestClientObservationAutoConfiguration {
4246

4347
@Bean
4448
RestClientCustomizer observationRestClientCustomizer(ObservationRegistry observationRegistry,
Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,17 @@
1414
* limitations under the License.
1515
*/
1616

17-
package org.springframework.boot.actuate.autoconfigure.observation.web.client;
17+
package org.springframework.boot.restclient.autoconfigure.observation;
1818

1919
import io.micrometer.observation.ObservationRegistry;
2020

2121
import org.springframework.beans.factory.ObjectProvider;
2222
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
2323
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
24+
import org.springframework.boot.context.properties.EnableConfigurationProperties;
2425
import org.springframework.boot.micrometer.observation.autoconfigure.ObservationProperties;
2526
import org.springframework.boot.restclient.RestTemplateBuilder;
26-
import org.springframework.boot.restclient.actuate.observation.ObservationRestTemplateCustomizer;
27+
import org.springframework.boot.restclient.observation.ObservationRestTemplateCustomizer;
2728
import org.springframework.context.annotation.Bean;
2829
import org.springframework.context.annotation.Configuration;
2930
import org.springframework.http.client.observation.ClientRequestObservationConvention;
@@ -34,11 +35,14 @@
3435
* Configure the instrumentation of {@link RestTemplate}.
3536
*
3637
* @author Brian Clozel
38+
* @since 4.0.0
3739
*/
3840
@Configuration(proxyBeanMethods = false)
39-
@ConditionalOnClass({ RestTemplate.class, ObservationRestTemplateCustomizer.class })
40-
@ConditionalOnBean(RestTemplateBuilder.class)
41-
class RestTemplateObservationConfiguration {
41+
@ConditionalOnClass({ RestTemplate.class, ObservationRestTemplateCustomizer.class, ObservationRegistry.class,
42+
ObservationProperties.class })
43+
@ConditionalOnBean({ ObservationRegistry.class, RestTemplateBuilder.class })
44+
@EnableConfigurationProperties(ObservationProperties.class)
45+
public class RestTemplateObservationAutoConfiguration {
4246

4347
@Bean
4448
ObservationRestTemplateCustomizer observationRestTemplateCustomizer(ObservationRegistry observationRegistry,

0 commit comments

Comments
 (0)