Skip to content

Commit 47ef6b8

Browse files
wilkinsonaphilwebb
authored andcommitted
Move HTTP client observation support into relevant modules
Issue: 46071
1 parent 6ee16a7 commit 47ef6b8

File tree

30 files changed

+253
-251
lines changed

30 files changed

+253
-251
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-http-client/build.gradle

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ dependencies {
3232
implementation(project(":spring-boot-project:spring-boot-http-converter"))
3333

3434
optional(project(":spring-boot-project:spring-boot-autoconfigure"))
35+
optional(project(":spring-boot-project:spring-boot-metrics"))
3536
optional(project(":spring-boot-project:spring-boot-reactor-netty"))
3637
optional("org.apache.httpcomponents.client5:httpclient5")
3738
optional("org.apache.httpcomponents.core5:httpcore5-reactive")
@@ -42,6 +43,7 @@ dependencies {
4243
testImplementation(project(":spring-boot-project:spring-boot-tomcat"))
4344
testImplementation(project(":spring-boot-project:spring-boot-tools:spring-boot-test-support"))
4445
testImplementation("org.springframework:spring-webflux")
46+
testImplementation("io.micrometer:micrometer-observation-test")
4547

4648
testRuntimeOnly("ch.qos.logback:logback-classic")
4749
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/*
2+
* Copyright 2012-present 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-present 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
@@ -31,10 +31,12 @@ dependencies {
3131
implementation(project(":spring-boot-project:spring-boot-http-converter"))
3232

3333
optional(project(":spring-boot-project:spring-boot-autoconfigure"))
34+
optional(project(":spring-boot-project:spring-boot-micrometer-observation"))
3435
optional("io.projectreactor.netty:reactor-netty-http")
3536
optional("org.apache.httpcomponents.client5:httpclient5")
3637
optional("org.eclipse.jetty:jetty-client")
3738

39+
testImplementation(project(":spring-boot-project:spring-boot-metrics"))
3840
testImplementation(project(":spring-boot-project:spring-boot-test"))
3941
testImplementation(project(":spring-boot-project:spring-boot-tomcat"))
4042
testImplementation(project(":spring-boot-project:spring-boot-tools:spring-boot-test-support"))
Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,19 @@
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;
22+
import org.springframework.boot.autoconfigure.AutoConfiguration;
2223
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
2324
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
25+
import org.springframework.boot.context.properties.EnableConfigurationProperties;
2426
import org.springframework.boot.micrometer.observation.autoconfigure.ObservationProperties;
2527
import org.springframework.boot.restclient.RestClientCustomizer;
26-
import org.springframework.boot.restclient.actuate.observation.ObservationRestClientCustomizer;
28+
import org.springframework.boot.restclient.observation.ObservationRestClientCustomizer;
2729
import org.springframework.context.annotation.Bean;
28-
import org.springframework.context.annotation.Configuration;
2930
import org.springframework.http.client.observation.ClientRequestObservationConvention;
3031
import org.springframework.http.client.observation.DefaultClientRequestObservationConvention;
3132
import org.springframework.web.client.RestClient;
@@ -34,11 +35,14 @@
3435
* Configure the instrumentation of {@link RestClient}.
3536
*
3637
* @author Moritz Halbritter
38+
* @since 4.0.0
3739
*/
38-
@Configuration(proxyBeanMethods = false)
39-
@ConditionalOnClass({ RestClient.class, ObservationRestClientCustomizer.class })
40-
@ConditionalOnBean(RestClient.Builder.class)
41-
class RestClientObservationConfiguration {
40+
@AutoConfiguration
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,

0 commit comments

Comments
 (0)