Browse Source

Make sure metricsExecutor is shutdown cleanly

The default executor for publishing metrics was a single
thread (native JDK) ExecutorService with a non-daemon thread.
Changed it to a Spring-managed thread pool of size 1, which
is then shutdown with e ApplicationContext automatically.

Fixes gh-388
pull/382/merge
Dave Syer 12 years ago
parent
commit
d98bfdea37
  1. 13
      spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/MetricRepositoryAutoConfiguration.java
  2. 14
      spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/MetricRepositoryAutoConfigurationTests.java

13
spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/MetricRepositoryAutoConfiguration.java

@ -18,7 +18,6 @@ package org.springframework.boot.actuate.autoconfigure;
import java.util.List; import java.util.List;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Qualifier;
@ -44,6 +43,7 @@ import org.springframework.context.annotation.Primary;
import org.springframework.messaging.MessageChannel; import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.SubscribableChannel; import org.springframework.messaging.SubscribableChannel;
import org.springframework.messaging.support.ExecutorSubscribableChannel; import org.springframework.messaging.support.ExecutorSubscribableChannel;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import com.codahale.metrics.MetricRegistry; import com.codahale.metrics.MetricRegistry;
@ -121,9 +121,9 @@ public class MetricRepositoryAutoConfiguration {
@ConditionalOnClass(MessageChannel.class) @ConditionalOnClass(MessageChannel.class)
static class MetricsChannelConfiguration { static class MetricsChannelConfiguration {
@Autowired(required = false) @Autowired
@Qualifier("metricsExecutor") @Qualifier("metricsExecutor")
private final Executor executor = Executors.newSingleThreadExecutor(); private Executor executor;
@Bean @Bean
@ConditionalOnMissingBean(name = "metricsChannel") @ConditionalOnMissingBean(name = "metricsChannel")
@ -131,6 +131,13 @@ public class MetricRepositoryAutoConfiguration {
return new ExecutorSubscribableChannel(this.executor); return new ExecutorSubscribableChannel(this.executor);
} }
@Bean
@ConditionalOnMissingBean(name = "metricsExecutor")
protected Executor metricsExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
return executor;
}
@Bean @Bean
@Primary @Primary
@ConditionalOnMissingBean(name = "primaryMetricWriter") @ConditionalOnMissingBean(name = "primaryMetricWriter")

14
spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/MetricRepositoryAutoConfigurationTests.java

@ -30,6 +30,8 @@ import org.springframework.context.annotation.AnnotationConfigApplicationContext
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.core.task.SyncTaskExecutor; import org.springframework.core.task.SyncTaskExecutor;
import org.springframework.messaging.support.ExecutorSubscribableChannel;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import com.codahale.metrics.Gauge; import com.codahale.metrics.Gauge;
import com.codahale.metrics.MetricRegistry; import com.codahale.metrics.MetricRegistry;
@ -38,6 +40,7 @@ import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat; import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.any; import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
@ -50,6 +53,17 @@ import static org.mockito.Mockito.verify;
*/ */
public class MetricRepositoryAutoConfigurationTests { public class MetricRepositoryAutoConfigurationTests {
@Test
public void defaultExecutor() throws Exception {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
MetricRepositoryAutoConfiguration.class);
ExecutorSubscribableChannel channel = context
.getBean(ExecutorSubscribableChannel.class);
ThreadPoolTaskExecutor executor = (ThreadPoolTaskExecutor) channel.getExecutor();
context.close();
assertTrue(executor.getThreadPoolExecutor().isShutdown());
}
@Test @Test
public void createServices() throws Exception { public void createServices() throws Exception {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext( AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(

Loading…
Cancel
Save