Fix MetricsFilter registration to support async
Update `WebMvcMetricsConfiguration` so that the filter is registered with the correct settings to support async requests. See gh-11348
This commit is contained in:
parent
25815ca7e1
commit
b6af06a55f
|
@ -16,6 +16,8 @@
|
|||
|
||||
package org.springframework.boot.actuate.autoconfigure.metrics.web.servlet;
|
||||
|
||||
import javax.servlet.DispatcherType;
|
||||
|
||||
import io.micrometer.core.instrument.MeterRegistry;
|
||||
|
||||
import org.springframework.boot.actuate.autoconfigure.metrics.MetricsProperties;
|
||||
|
@ -27,6 +29,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
|||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
|
@ -51,13 +54,17 @@ public class WebMvcMetricsConfiguration {
|
|||
}
|
||||
|
||||
@Bean
|
||||
public WebMvcMetricsFilter webMetricsFilter(MeterRegistry registry,
|
||||
MetricsProperties properties, WebMvcTagsProvider tagsProvider,
|
||||
WebApplicationContext context) {
|
||||
public FilterRegistrationBean<WebMvcMetricsFilter> webMetricsFilter(
|
||||
MeterRegistry registry, MetricsProperties properties,
|
||||
WebMvcTagsProvider tagsProvider, WebApplicationContext context) {
|
||||
Server serverProperties = properties.getWeb().getServer();
|
||||
return new WebMvcMetricsFilter(context, registry, tagsProvider,
|
||||
serverProperties.getRequestsMetricName(),
|
||||
WebMvcMetricsFilter filter = new WebMvcMetricsFilter(context, registry,
|
||||
tagsProvider, serverProperties.getRequestsMetricName(),
|
||||
serverProperties.isAutoTimeRequests());
|
||||
FilterRegistrationBean<WebMvcMetricsFilter> registration = new FilterRegistrationBean<>(
|
||||
filter);
|
||||
registration.setDispatcherTypes(DispatcherType.REQUEST, DispatcherType.ASYNC);
|
||||
return registration;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -19,6 +19,10 @@ package org.springframework.boot.actuate.autoconfigure.metrics;
|
|||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.BrokenBarrierException;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.CyclicBarrier;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import io.micrometer.core.instrument.MeterRegistry;
|
||||
import io.micrometer.core.instrument.MockClock;
|
||||
|
@ -83,6 +87,9 @@ public class MetricsAutoConfigurationIntegrationTests {
|
|||
@Autowired
|
||||
private MeterRegistry registry;
|
||||
|
||||
@Autowired
|
||||
private CyclicBarrier cyclicBarrier;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void restTemplateIsInstrumented() {
|
||||
|
@ -111,6 +118,21 @@ public class MetricsAutoConfigurationIntegrationTests {
|
|||
.hasAtLeastOneElementOfType(JvmMemoryMetrics.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void asyncRequestMappingIsInstrumented() throws InterruptedException, BrokenBarrierException {
|
||||
Thread backgroundRequest = new Thread(() -> this.loopback.getForObject("/api/async", String.class));
|
||||
backgroundRequest.start();
|
||||
this.cyclicBarrier.await();
|
||||
MockClock.clock(this.registry).addSeconds(2);
|
||||
this.cyclicBarrier.await();
|
||||
backgroundRequest.join();
|
||||
|
||||
assertThat(this.registry.find("http.server.requests")
|
||||
.tags("uri", "/api/async").timer())
|
||||
.matches(t -> t.count() == 1)
|
||||
.matches(t -> t.totalTime(TimeUnit.SECONDS) == 2);
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ImportAutoConfiguration({ MetricsAutoConfiguration.class,
|
||||
JacksonAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class,
|
||||
|
@ -130,16 +152,38 @@ public class MetricsAutoConfigurationIntegrationTests {
|
|||
return restTemplateBuilder.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public CyclicBarrier cyclicBarrier() {
|
||||
return new CyclicBarrier(2);
|
||||
}
|
||||
}
|
||||
|
||||
@RestController
|
||||
static class PersonController {
|
||||
private final CyclicBarrier cyclicBarrier;
|
||||
|
||||
PersonController(CyclicBarrier cyclicBarrier) {
|
||||
this.cyclicBarrier = cyclicBarrier;
|
||||
}
|
||||
|
||||
@GetMapping("/api/people")
|
||||
Set<String> personName() {
|
||||
return Collections.singleton("Jon");
|
||||
}
|
||||
|
||||
@GetMapping("/api/async")
|
||||
CompletableFuture<String> asyncHello() throws BrokenBarrierException, InterruptedException {
|
||||
this.cyclicBarrier.await();
|
||||
return CompletableFuture.supplyAsync(() -> {
|
||||
try {
|
||||
this.cyclicBarrier.await();
|
||||
}
|
||||
catch (InterruptedException | BrokenBarrierException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return "async-hello";
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue