diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/AbstractMetricExporter.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/AbstractMetricExporter.java index 6bc35191fa..05a7782f7d 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/AbstractMetricExporter.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/AbstractMetricExporter.java @@ -16,6 +16,9 @@ package org.springframework.boot.actuate.metrics.export; +import java.io.Closeable; +import java.io.Flushable; +import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -36,7 +39,7 @@ import org.springframework.util.StringUtils; * @author Dave Syer * @since 1.3.0 */ -public abstract class AbstractMetricExporter implements Exporter { +public abstract class AbstractMetricExporter implements Exporter, Closeable, Flushable { private static final Log logger = LogFactory.getLog(AbstractMetricExporter.class); @@ -143,6 +146,13 @@ public abstract class AbstractMetricExporter implements Exporter { } } + @Override + public void close() throws IOException { + export(); + flushQuietly(); + } + + @Override public void flush() { } diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/MetricExporters.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/MetricExporters.java index ceb2095a1b..204c7e48a1 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/MetricExporters.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/MetricExporters.java @@ -16,9 +16,13 @@ package org.springframework.boot.actuate.metrics.export; +import java.io.Closeable; +import java.io.IOException; import java.util.HashMap; +import java.util.HashSet; import java.util.Map; import java.util.Map.Entry; +import java.util.Set; import org.springframework.boot.actuate.metrics.reader.MetricReader; import org.springframework.boot.actuate.metrics.writer.GaugeWriter; @@ -32,7 +36,7 @@ import org.springframework.scheduling.config.ScheduledTaskRegistrar; * @author Dave Syer * @since 1.3.0 */ -public class MetricExporters implements SchedulingConfigurer { +public class MetricExporters implements SchedulingConfigurer, Closeable { private MetricReader reader; @@ -42,6 +46,8 @@ public class MetricExporters implements SchedulingConfigurer { private final Map exporters = new HashMap(); + private final Set closeables = new HashSet(); + public MetricExporters(MetricExportProperties properties) { this.properties = properties; } @@ -78,6 +84,7 @@ public class MetricExporters implements SchedulingConfigurer { if (trigger != null) { MetricCopyExporter exporter = getExporter(writer, trigger); this.exporters.put(name, exporter); + this.closeables.add(name); ExportRunner runner = new ExportRunner(exporter); IntervalTask task = new IntervalTask(runner, trigger.getDelayMillis(), trigger.getDelayMillis()); @@ -99,6 +106,16 @@ public class MetricExporters implements SchedulingConfigurer { return this.exporters; } + @Override + public void close() throws IOException { + for (String name : this.closeables) { + Exporter exporter = this.exporters.get(name); + if (exporter instanceof Closeable) { + ((Closeable) exporter).close(); + } + } + } + private static class ExportRunner implements Runnable { private final Exporter exporter; diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/MetricExportAutoConfigurationTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/MetricExportAutoConfigurationTests.java index 170258fd6b..08a5e440ce 100644 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/MetricExportAutoConfigurationTests.java +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/MetricExportAutoConfigurationTests.java @@ -68,6 +68,21 @@ public class MetricExportAutoConfigurationTests { } } + @Test + public void metricsFlushAutomatically() throws Exception { + this.context = new AnnotationConfigApplicationContext(WriterConfig.class, + MetricRepositoryAutoConfiguration.class, + MetricExportAutoConfiguration.class, + PropertyPlaceholderAutoConfiguration.class); + GaugeService gaugeService = this.context.getBean(GaugeService.class); + assertNotNull(gaugeService); + gaugeService.submit("foo", 2.7); + MetricExporters flusher = this.context.getBean(MetricExporters.class); + flusher.close(); // this will be called by Spring on shutdown + MetricWriter writer = this.context.getBean("writer", MetricWriter.class); + Mockito.verify(writer, Mockito.atLeastOnce()).set(Matchers.any(Metric.class)); + } + @Test public void defaultExporterWhenMessageChannelAvailable() throws Exception { this.context = new AnnotationConfigApplicationContext(