Harmonize HTTP client metrics

This commit harmonizes the auto-configurations for RestTemplate and
WebClient in a single `HttpClientMetricsAutoConfiguration`. Doing so
allows to give a better scope for the shared `MeterFilter`.

As a result`WebClientMetricsAutoConfiguration` has moved to the `client`
package.

Closes gh-14269
pull/14255/head
Stephane Nicoll 6 years ago
parent 2fc557a5a9
commit 7bee9dfc22

@ -23,62 +23,44 @@ import org.springframework.boot.actuate.autoconfigure.metrics.MetricsAutoConfigu
import org.springframework.boot.actuate.autoconfigure.metrics.MetricsProperties; import org.springframework.boot.actuate.autoconfigure.metrics.MetricsProperties;
import org.springframework.boot.actuate.autoconfigure.metrics.OnlyOnceLoggingDenyMeterFilter; import org.springframework.boot.actuate.autoconfigure.metrics.OnlyOnceLoggingDenyMeterFilter;
import org.springframework.boot.actuate.autoconfigure.metrics.export.simple.SimpleMetricsExportAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.metrics.export.simple.SimpleMetricsExportAutoConfiguration;
import org.springframework.boot.actuate.metrics.web.client.DefaultRestTemplateExchangeTagsProvider;
import org.springframework.boot.actuate.metrics.web.client.MetricsRestTemplateCustomizer;
import org.springframework.boot.actuate.metrics.web.client.RestTemplateExchangeTagsProvider;
import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.core.annotation.Order; import org.springframework.core.annotation.Order;
import org.springframework.web.client.RestTemplate;
/** /**
* {@link EnableAutoConfiguration Auto-configuration} for {@link RestTemplate}-related * {@link EnableAutoConfiguration Auto-configuration} for HTTP client-related metrics.
* metrics.
* *
* @author Jon Schneider * @author Jon Schneider
* @author Phillip Webb * @author Phillip Webb
* @since 2.0.0 * @author Stephane Nicoll
* @since 2.1.0
*/ */
@Configuration @Configuration
@AutoConfigureAfter({ MetricsAutoConfiguration.class, RestTemplateAutoConfiguration.class, @AutoConfigureAfter({ MetricsAutoConfiguration.class,
SimpleMetricsExportAutoConfiguration.class }) SimpleMetricsExportAutoConfiguration.class })
@ConditionalOnClass(RestTemplate.class) @ConditionalOnClass(MeterRegistry.class)
@ConditionalOnBean(MeterRegistry.class) @ConditionalOnBean(MeterRegistry.class)
public class RestTemplateMetricsAutoConfiguration { @Import({ RestTemplateMetricsConfiguration.class, WebClientMetricsConfiguration.class })
public class HttpClientMetricsAutoConfiguration {
private final MetricsProperties properties; private final MetricsProperties properties;
public RestTemplateMetricsAutoConfiguration(MetricsProperties properties) { public HttpClientMetricsAutoConfiguration(MetricsProperties properties) {
this.properties = properties; this.properties = properties;
} }
@Bean
@ConditionalOnMissingBean(RestTemplateExchangeTagsProvider.class)
public DefaultRestTemplateExchangeTagsProvider restTemplateTagConfigurer() {
return new DefaultRestTemplateExchangeTagsProvider();
}
@Bean
public MetricsRestTemplateCustomizer metricsRestTemplateCustomizer(
MeterRegistry meterRegistry,
RestTemplateExchangeTagsProvider restTemplateTagConfigurer) {
return new MetricsRestTemplateCustomizer(meterRegistry, restTemplateTagConfigurer,
this.properties.getWeb().getClient().getRequestsMetricName());
}
@Bean @Bean
@Order(0) @Order(0)
public MeterFilter metricsHttpClientUriTagFilter() { public MeterFilter metricsHttpClientUriTagFilter() {
String metricName = this.properties.getWeb().getClient().getRequestsMetricName(); String metricName = this.properties.getWeb().getClient().getRequestsMetricName();
MeterFilter denyFilter = new OnlyOnceLoggingDenyMeterFilter(() -> String MeterFilter denyFilter = new OnlyOnceLoggingDenyMeterFilter(() -> String
.format("Reached the maximum number of URI tags for '%s'. Are you using " .format("Reached the maximum number of URI tags for '%s'. Are you using "
+ "'uriVariables' on RestTemplate calls?", metricName)); + "'uriVariables'?", metricName));
return MeterFilter.maximumAllowableTags(metricName, "uri", return MeterFilter.maximumAllowableTags(metricName, "uri",
this.properties.getWeb().getClient().getMaxUriTags(), denyFilter); this.properties.getWeb().getClient().getMaxUriTags(), denyFilter);
} }

@ -0,0 +1,61 @@
/*
* Copyright 2012-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.boot.actuate.autoconfigure.metrics.web.client;
import io.micrometer.core.instrument.MeterRegistry;
import org.springframework.boot.actuate.autoconfigure.metrics.MetricsProperties;
import org.springframework.boot.actuate.metrics.web.client.DefaultRestTemplateExchangeTagsProvider;
import org.springframework.boot.actuate.metrics.web.client.MetricsRestTemplateCustomizer;
import org.springframework.boot.actuate.metrics.web.client.RestTemplateExchangeTagsProvider;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
/**
* Configure the instrumentation of {@link RestTemplate}.
*
* @author Jon Schneider
* @author Phillip Webb
*/
@Configuration
@ConditionalOnClass(RestTemplate.class)
class RestTemplateMetricsConfiguration {
private final MetricsProperties properties;
RestTemplateMetricsConfiguration(MetricsProperties properties) {
this.properties = properties;
}
@Bean
@ConditionalOnMissingBean(RestTemplateExchangeTagsProvider.class)
public DefaultRestTemplateExchangeTagsProvider restTemplateTagConfigurer() {
return new DefaultRestTemplateExchangeTagsProvider();
}
@Bean
public MetricsRestTemplateCustomizer metricsRestTemplateCustomizer(
MeterRegistry meterRegistry,
RestTemplateExchangeTagsProvider restTemplateTagConfigurer) {
return new MetricsRestTemplateCustomizer(meterRegistry, restTemplateTagConfigurer,
this.properties.getWeb().getClient().getRequestsMetricName());
}
}

@ -14,46 +14,29 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.boot.actuate.autoconfigure.metrics.web.reactive; package org.springframework.boot.actuate.autoconfigure.metrics.web.client;
import io.micrometer.core.instrument.MeterRegistry; import io.micrometer.core.instrument.MeterRegistry;
import org.springframework.boot.actuate.autoconfigure.metrics.MetricsAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.metrics.MetricsProperties; import org.springframework.boot.actuate.autoconfigure.metrics.MetricsProperties;
import org.springframework.boot.actuate.autoconfigure.metrics.export.simple.SimpleMetricsExportAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.metrics.web.client.RestTemplateMetricsAutoConfiguration;
import org.springframework.boot.actuate.metrics.web.reactive.client.DefaultWebClientExchangeTagsProvider; import org.springframework.boot.actuate.metrics.web.reactive.client.DefaultWebClientExchangeTagsProvider;
import org.springframework.boot.actuate.metrics.web.reactive.client.MetricsWebClientCustomizer; import org.springframework.boot.actuate.metrics.web.reactive.client.MetricsWebClientCustomizer;
import org.springframework.boot.actuate.metrics.web.reactive.client.WebClientExchangeTagsProvider; import org.springframework.boot.actuate.metrics.web.reactive.client.WebClientExchangeTagsProvider;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.web.reactive.function.client.WebClient; import org.springframework.web.reactive.function.client.WebClient;
/** /**
* {@link EnableAutoConfiguration Auto-configuration} for instrumentation of * Configure the instrumentation of {@link WebClient}.
* {@link org.springframework.web.reactive.function.client.WebClient}.
* <p>
* This is reusing the {@link io.micrometer.core.instrument.config.MeterFilter} defined in
* {@link RestTemplateMetricsAutoConfiguration} for limiting the cardinality of "uri"
* tags.
* *
* @author Brian Clozel * @author Brian Clozel
* @since 2.1.0 * @author Stephane Nicoll
*/ */
@Configuration @Configuration
@ConditionalOnClass(WebClient.class) @ConditionalOnClass(WebClient.class)
@AutoConfigureAfter({ MetricsAutoConfiguration.class, class WebClientMetricsConfiguration {
SimpleMetricsExportAutoConfiguration.class })
@AutoConfigureBefore(WebClientAutoConfiguration.class)
@ConditionalOnBean(MeterRegistry.class)
public class WebClientMetricsAutoConfiguration {
@Bean @Bean
@ConditionalOnMissingBean @ConditionalOnMissingBean

@ -52,8 +52,7 @@ org.springframework.boot.actuate.autoconfigure.metrics.export.statsd.StatsdMetri
org.springframework.boot.actuate.autoconfigure.metrics.export.wavefront.WavefrontMetricsExportAutoConfiguration,\ org.springframework.boot.actuate.autoconfigure.metrics.export.wavefront.WavefrontMetricsExportAutoConfiguration,\
org.springframework.boot.actuate.autoconfigure.metrics.jdbc.DataSourcePoolMetricsAutoConfiguration,\ org.springframework.boot.actuate.autoconfigure.metrics.jdbc.DataSourcePoolMetricsAutoConfiguration,\
org.springframework.boot.actuate.autoconfigure.metrics.orm.jpa.HibernateMetricsAutoConfiguration,\ org.springframework.boot.actuate.autoconfigure.metrics.orm.jpa.HibernateMetricsAutoConfiguration,\
org.springframework.boot.actuate.autoconfigure.metrics.web.client.RestTemplateMetricsAutoConfiguration,\ org.springframework.boot.actuate.autoconfigure.metrics.web.client.HttpClientMetricsAutoConfiguration,\
org.springframework.boot.actuate.autoconfigure.metrics.web.reactive.WebClientMetricsAutoConfiguration,\
org.springframework.boot.actuate.autoconfigure.metrics.web.reactive.WebFluxMetricsAutoConfiguration,\ org.springframework.boot.actuate.autoconfigure.metrics.web.reactive.WebFluxMetricsAutoConfiguration,\
org.springframework.boot.actuate.autoconfigure.metrics.web.servlet.WebMvcMetricsAutoConfiguration,\ org.springframework.boot.actuate.autoconfigure.metrics.web.servlet.WebMvcMetricsAutoConfiguration,\
org.springframework.boot.actuate.autoconfigure.metrics.web.tomcat.TomcatMetricsAutoConfiguration,\ org.springframework.boot.actuate.autoconfigure.metrics.web.tomcat.TomcatMetricsAutoConfiguration,\

@ -39,7 +39,7 @@ import org.springframework.boot.actuate.autoconfigure.metrics.amqp.RabbitMetrics
import org.springframework.boot.actuate.autoconfigure.metrics.cache.CacheMetricsAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.metrics.cache.CacheMetricsAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.metrics.jdbc.DataSourcePoolMetricsAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.metrics.jdbc.DataSourcePoolMetricsAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.metrics.orm.jpa.HibernateMetricsAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.metrics.orm.jpa.HibernateMetricsAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.metrics.web.client.RestTemplateMetricsAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.metrics.web.client.HttpClientMetricsAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.metrics.web.reactive.WebFluxMetricsAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.metrics.web.reactive.WebFluxMetricsAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.metrics.web.servlet.WebMvcMetricsAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.metrics.web.servlet.WebMvcMetricsAutoConfiguration;
import org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter; import org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter;
@ -143,7 +143,7 @@ public class MetricsIntegrationTests {
RabbitMetricsAutoConfiguration.class, CacheMetricsAutoConfiguration.class, RabbitMetricsAutoConfiguration.class, CacheMetricsAutoConfiguration.class,
DataSourcePoolMetricsAutoConfiguration.class, DataSourcePoolMetricsAutoConfiguration.class,
HibernateMetricsAutoConfiguration.class, HibernateMetricsAutoConfiguration.class,
RestTemplateMetricsAutoConfiguration.class, HttpClientMetricsAutoConfiguration.class,
WebFluxMetricsAutoConfiguration.class, WebMvcMetricsAutoConfiguration.class, WebFluxMetricsAutoConfiguration.class, WebMvcMetricsAutoConfiguration.class,
JacksonAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class, JacksonAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class,
RestTemplateAutoConfiguration.class, WebMvcAutoConfiguration.class, RestTemplateAutoConfiguration.class, WebMvcAutoConfiguration.class,

@ -38,8 +38,7 @@ import org.springframework.boot.actuate.autoconfigure.metrics.export.simple.Simp
import org.springframework.boot.actuate.autoconfigure.metrics.export.statsd.StatsdMetricsExportAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.metrics.export.statsd.StatsdMetricsExportAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.metrics.jdbc.DataSourcePoolMetricsAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.metrics.jdbc.DataSourcePoolMetricsAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.metrics.orm.jpa.HibernateMetricsAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.metrics.orm.jpa.HibernateMetricsAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.metrics.web.client.RestTemplateMetricsAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.metrics.web.client.HttpClientMetricsAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.metrics.web.reactive.WebClientMetricsAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.metrics.web.reactive.WebFluxMetricsAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.metrics.web.reactive.WebFluxMetricsAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.metrics.web.servlet.WebMvcMetricsAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.metrics.web.servlet.WebMvcMetricsAutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.AutoConfigurations;
@ -78,8 +77,7 @@ public final class MetricsRun {
RabbitMetricsAutoConfiguration.class, CacheMetricsAutoConfiguration.class, RabbitMetricsAutoConfiguration.class, CacheMetricsAutoConfiguration.class,
DataSourcePoolMetricsAutoConfiguration.class, DataSourcePoolMetricsAutoConfiguration.class,
HibernateMetricsAutoConfiguration.class, HibernateMetricsAutoConfiguration.class,
RestTemplateMetricsAutoConfiguration.class, HttpClientMetricsAutoConfiguration.class,
WebClientMetricsAutoConfiguration.class,
WebFluxMetricsAutoConfiguration.class, WebMvcMetricsAutoConfiguration.class); WebFluxMetricsAutoConfiguration.class, WebMvcMetricsAutoConfiguration.class);
private MetricsRun() { private MetricsRun() {

@ -37,12 +37,12 @@ import static org.springframework.test.web.client.match.MockRestRequestMatchers.
import static org.springframework.test.web.client.response.MockRestResponseCreators.withStatus; import static org.springframework.test.web.client.response.MockRestResponseCreators.withStatus;
/** /**
* Tests for {@link RestTemplateMetricsAutoConfiguration}. * Tests for {@link RestTemplateMetricsConfiguration}.
* *
* @author Stephane Nicoll * @author Stephane Nicoll
* @author Jon Schneider * @author Jon Schneider
*/ */
public class RestTemplateMetricsAutoConfigurationTests { public class RestTemplateMetricsConfigurationTests {
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.with(MetricsRun.simple()).withConfiguration( .with(MetricsRun.simple()).withConfiguration(
@ -82,8 +82,8 @@ public class RestTemplateMetricsAutoConfigurationTests {
assertThat(registry.get("http.client.requests").meters()).hasSize(2); assertThat(registry.get("http.client.requests").meters()).hasSize(2);
assertThat(this.out.toString()).contains( assertThat(this.out.toString()).contains(
"Reached the maximum number of URI tags for 'http.client.requests'."); "Reached the maximum number of URI tags for 'http.client.requests'.");
assertThat(this.out.toString()).contains( assertThat(this.out.toString())
"Are you using 'uriVariables' on RestTemplate calls?"); .contains("Are you using 'uriVariables'?");
}); });
} }

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.boot.actuate.autoconfigure.metrics.web.reactive; package org.springframework.boot.actuate.autoconfigure.metrics.web.client;
import io.micrometer.core.instrument.MeterRegistry; import io.micrometer.core.instrument.MeterRegistry;
import org.junit.Before; import org.junit.Before;
@ -42,11 +42,11 @@ import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
/** /**
* Tests for {@link WebClientMetricsAutoConfiguration} * Tests for {@link WebClientMetricsConfiguration}
* *
* @author Brian Clozel * @author Brian Clozel
*/ */
public class WebClientMetricsAutoConfigurationTests { public class WebClientMetricsConfigurationTests {
private ApplicationContextRunner contextRunner = new ApplicationContextRunner() private ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.with(MetricsRun.simple()) .with(MetricsRun.simple())
@ -103,9 +103,10 @@ public class WebClientMetricsAutoConfigurationTests {
} }
assertThat(registry.get("http.client.requests").meters()) assertThat(registry.get("http.client.requests").meters())
.hasSize(maxUriTags); .hasSize(maxUriTags);
assertThat(this.out.toString()).contains(
"Reached the maximum number of URI tags for 'http.client.requests'.");
assertThat(this.out.toString()) assertThat(this.out.toString())
.contains("Reached the maximum number of URI tags " .contains("Are you using 'uriVariables'?");
+ "for 'http.client.requests'");
}); });
} }
Loading…
Cancel
Save