Merge pull request #11348 from GreyTeardrop
* pr/11348: Polish MetricsFilter registration async support Fix MetricsFilter registration to support async
This commit is contained in:
		
						commit
						a3c6e72ec6
					
				| 
						 | 
				
			
			@ -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,44 @@ 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(this::awaitAndHello);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private String awaitAndHello() {
 | 
			
		||||
			try {
 | 
			
		||||
				this.cyclicBarrier.await();
 | 
			
		||||
				return "async-hello";
 | 
			
		||||
			}
 | 
			
		||||
			catch (InterruptedException | BrokenBarrierException ex) {
 | 
			
		||||
				throw new RuntimeException(ex);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue