mirror of
https://github.com/spring-projects/spring-boot.git
synced 2024-08-29 03:06:45 +08:00
Add metric flusher to export remaining metrics on shutdown
Before this change the app context closes and metrics that have not yet been exported ccan be orphaned. The design of this feature is simple: use Closeable where possible, so that it will be called automatically by Spring on shutdown. Fixes gh-5771
This commit is contained in:
parent
de0f0ecce4
commit
b9db4742ac
@ -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() {
|
||||
}
|
||||
|
||||
|
@ -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<String, Exporter> exporters = new HashMap<String, Exporter>();
|
||||
|
||||
private final Set<String> closeables = new HashSet<String>();
|
||||
|
||||
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;
|
||||
|
@ -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(
|
||||
|
Loading…
Reference in New Issue
Block a user