Decouple AutoTimeProperties from Micrometer Core

Closes gh-32676
This commit is contained in:
Andy Wilkinson
2022-10-12 14:40:42 +01:00
parent 7e9e64a2ea
commit 180d0edbca
7 changed files with 137 additions and 15 deletions

View File

@@ -16,10 +16,6 @@
package org.springframework.boot.actuate.autoconfigure.metrics;
import io.micrometer.core.instrument.Timer.Builder;
import org.springframework.boot.actuate.metrics.AutoTimer;
/**
* Nested configuration properties for items that are automatically timed.
*
@@ -28,7 +24,7 @@ import org.springframework.boot.actuate.metrics.AutoTimer;
* @author Phillip Webb
* @since 2.2.0
*/
public final class AutoTimeProperties implements AutoTimer {
public final class AutoTimeProperties {
/**
* Whether to enable auto-timing.
@@ -51,7 +47,6 @@ public final class AutoTimeProperties implements AutoTimer {
public AutoTimeProperties() {
}
@Override
public boolean isEnabled() {
return this.enabled;
}
@@ -76,9 +71,4 @@ public final class AutoTimeProperties implements AutoTimer {
this.percentiles = percentiles;
}
@Override
public void apply(Builder builder) {
builder.publishPercentileHistogram(this.percentilesHistogram).publishPercentiles(this.percentiles);
}
}

View File

@@ -0,0 +1,53 @@
/*
* Copyright 2012-2022 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
*
* https://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;
import io.micrometer.core.instrument.Timer.Builder;
import org.springframework.boot.actuate.metrics.AutoTimer;
/**
* {@link AutoTimer} whose behavior is configured by {@link AutoTimeProperties}.
*
* @author Andy Wilkinson
* @since 3.0.0
*/
public class PropertiesAutoTimer implements AutoTimer {
private final AutoTimeProperties properties;
/**
* Create a new {@link PropertiesAutoTimer} configured using the given
* {@code properties}.
* @param properties the properties to configure auto-timing
*/
public PropertiesAutoTimer(AutoTimeProperties properties) {
this.properties = properties;
}
@Override
public void apply(Builder builder) {
builder.publishPercentileHistogram(this.properties.isPercentilesHistogram())
.publishPercentiles(this.properties.getPercentiles());
}
@Override
public boolean isEnabled() {
return this.properties.isEnabled();
}
}

View File

@@ -23,6 +23,7 @@ import org.springframework.boot.actuate.autoconfigure.metrics.CompositeMeterRegi
import org.springframework.boot.actuate.autoconfigure.metrics.MetricsAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.metrics.MetricsProperties;
import org.springframework.boot.actuate.autoconfigure.metrics.MetricsProperties.Data.Repository;
import org.springframework.boot.actuate.autoconfigure.metrics.PropertiesAutoTimer;
import org.springframework.boot.actuate.autoconfigure.metrics.export.simple.SimpleMetricsExportAutoConfiguration;
import org.springframework.boot.actuate.metrics.data.DefaultRepositoryTagsProvider;
import org.springframework.boot.actuate.metrics.data.MetricsRepositoryMethodInvocationListener;
@@ -67,7 +68,7 @@ public class RepositoryMetricsAutoConfiguration {
ObjectProvider<MeterRegistry> registry, RepositoryTagsProvider tagsProvider) {
Repository properties = this.properties.getData().getRepository();
return new MetricsRepositoryMethodInvocationListener(registry::getObject, tagsProvider,
properties.getMetricName(), properties.getAutotime());
properties.getMetricName(), new PropertiesAutoTimer(properties.getAutotime()));
}
@Bean

View File

@@ -23,6 +23,7 @@ import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.actuate.autoconfigure.metrics.CompositeMeterRegistryAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.metrics.MetricsAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.metrics.MetricsProperties;
import org.springframework.boot.actuate.autoconfigure.metrics.PropertiesAutoTimer;
import org.springframework.boot.actuate.autoconfigure.metrics.export.simple.SimpleMetricsExportAutoConfiguration;
import org.springframework.boot.actuate.metrics.graphql.DefaultGraphQlTagsProvider;
import org.springframework.boot.actuate.metrics.graphql.GraphQlMetricsInstrumentation;
@@ -60,7 +61,8 @@ public class GraphQlMetricsAutoConfiguration {
@Bean
public GraphQlMetricsInstrumentation graphQlMetricsInstrumentation(MeterRegistry meterRegistry,
GraphQlTagsProvider tagsProvider, MetricsProperties properties) {
return new GraphQlMetricsInstrumentation(meterRegistry, tagsProvider, properties.getGraphql().getAutotime());
return new GraphQlMetricsInstrumentation(meterRegistry, tagsProvider,
new PropertiesAutoTimer(properties.getGraphql().getAutotime()));
}
}

View File

@@ -25,6 +25,7 @@ import org.springframework.boot.actuate.autoconfigure.metrics.MetricsAutoConfigu
import org.springframework.boot.actuate.autoconfigure.metrics.MetricsProperties;
import org.springframework.boot.actuate.autoconfigure.metrics.MetricsProperties.Web.Server.ServerRequest;
import org.springframework.boot.actuate.autoconfigure.metrics.OnlyOnceLoggingDenyMeterFilter;
import org.springframework.boot.actuate.autoconfigure.metrics.PropertiesAutoTimer;
import org.springframework.boot.actuate.autoconfigure.metrics.export.simple.SimpleMetricsExportAutoConfiguration;
import org.springframework.boot.actuate.metrics.web.reactive.server.DefaultWebFluxTagsProvider;
import org.springframework.boot.actuate.metrics.web.reactive.server.MetricsWebFilter;
@@ -68,7 +69,8 @@ public class WebFluxMetricsAutoConfiguration {
@Bean
public MetricsWebFilter webfluxMetrics(MeterRegistry registry, WebFluxTagsProvider tagConfigurer) {
ServerRequest request = this.properties.getWeb().getServer().getRequest();
return new MetricsWebFilter(registry, tagConfigurer, request.getMetricName(), request.getAutotime());
return new MetricsWebFilter(registry, tagConfigurer, request.getMetricName(),
new PropertiesAutoTimer(request.getAutotime()));
}
@Bean

View File

@@ -26,6 +26,7 @@ import org.springframework.boot.actuate.autoconfigure.metrics.MetricsAutoConfigu
import org.springframework.boot.actuate.autoconfigure.metrics.MetricsProperties;
import org.springframework.boot.actuate.autoconfigure.metrics.MetricsProperties.Web.Server.ServerRequest;
import org.springframework.boot.actuate.autoconfigure.metrics.OnlyOnceLoggingDenyMeterFilter;
import org.springframework.boot.actuate.autoconfigure.metrics.PropertiesAutoTimer;
import org.springframework.boot.actuate.autoconfigure.metrics.export.simple.SimpleMetricsExportAutoConfiguration;
import org.springframework.boot.actuate.metrics.web.servlet.DefaultWebMvcTagsProvider;
import org.springframework.boot.actuate.metrics.web.servlet.LongTaskTimingHandlerInterceptor;
@@ -83,7 +84,7 @@ public class WebMvcMetricsAutoConfiguration {
WebMvcTagsProvider tagsProvider) {
ServerRequest request = this.properties.getWeb().getServer().getRequest();
WebMvcMetricsFilter filter = new WebMvcMetricsFilter(registry, tagsProvider, request.getMetricName(),
request.getAutotime());
new PropertiesAutoTimer(request.getAutotime()));
FilterRegistrationBean<WebMvcMetricsFilter> registration = new FilterRegistrationBean<>(filter);
registration.setOrder(Ordered.HIGHEST_PRECEDENCE + 1);
registration.setDispatcherTypes(DispatcherType.REQUEST, DispatcherType.ASYNC);

View File

@@ -0,0 +1,73 @@
/*
* Copyright 2012-2022 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
*
* https://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.observation.ObservationRegistry;
import io.micrometer.observation.tck.TestObservationRegistry;
import io.micrometer.observation.tck.TestObservationRegistryAssert;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.boot.actuate.autoconfigure.observation.ObservationAutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration;
import org.springframework.boot.test.context.assertj.AssertableApplicationContext;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.boot.test.system.OutputCaptureExtension;
import org.springframework.boot.testsupport.classpath.ClassPathExclusions;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.http.HttpStatus;
import org.springframework.test.web.client.MockRestServiceServer;
import org.springframework.web.client.RestTemplate;
import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo;
import static org.springframework.test.web.client.response.MockRestResponseCreators.withStatus;
/**
* Tests for {@link RestTemplateObservationConfiguration} without Micrometer Metrics.
*
* @author Brian Clozel
* @author Andy Wilkinson
*/
@ExtendWith(OutputCaptureExtension.class)
@ClassPathExclusions("micrometer-core-*.jar")
class RestTemplateObservationConfigurationWithoutMetricsTests {
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withBean(ObservationRegistry.class, TestObservationRegistry::create)
.withConfiguration(AutoConfigurations.of(ObservationAutoConfiguration.class,
RestTemplateAutoConfiguration.class, HttpClientObservationsAutoConfiguration.class));
@Test
void restTemplateCreatedWithBuilderIsInstrumented() {
this.contextRunner.run((context) -> {
RestTemplate restTemplate = buildRestTemplate(context);
restTemplate.getForEntity("/projects/{project}", Void.class, "spring-boot");
TestObservationRegistry registry = context.getBean(TestObservationRegistry.class);
TestObservationRegistryAssert.assertThat(registry)
.hasObservationWithNameEqualToIgnoringCase("http.client.requests");
});
}
private RestTemplate buildRestTemplate(AssertableApplicationContext context) {
RestTemplate restTemplate = context.getBean(RestTemplateBuilder.class).build();
MockRestServiceServer server = MockRestServiceServer.createServer(restTemplate);
server.expect(requestTo("/projects/spring-boot")).andRespond(withStatus(HttpStatus.OK));
return restTemplate;
}
}