diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/PrefixMetricGroupExporter.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/PrefixMetricGroupExporter.java index c08a5481727..09cf71ee071 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/PrefixMetricGroupExporter.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/PrefixMetricGroupExporter.java @@ -19,10 +19,13 @@ package org.springframework.boot.actuate.metrics.export; import java.util.Collection; import java.util.HashSet; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; import org.springframework.boot.actuate.metrics.Metric; import org.springframework.boot.actuate.metrics.reader.PrefixMetricReader; import org.springframework.boot.actuate.metrics.repository.MultiMetricRepository; +import org.springframework.boot.actuate.metrics.writer.Delta; import org.springframework.boot.actuate.metrics.writer.PrefixMetricWriter; /** @@ -38,6 +41,8 @@ public class PrefixMetricGroupExporter extends AbstractMetricExporter { private final PrefixMetricWriter writer; + private ConcurrentMap counts = new ConcurrentHashMap(); + private Set groups = new HashSet(); /** @@ -88,7 +93,26 @@ public class PrefixMetricGroupExporter extends AbstractMetricExporter { @Override protected void write(String group, Collection> values) { - this.writer.set(group, values); + if (group.contains("counter.")) { + for (Metric value : values) { + this.writer.increment(group, calculateDelta(value)); + } + } + else { + this.writer.set(group, values); + } + } + + private Delta calculateDelta(Metric value) { + long delta = value.getValue().longValue(); + Long old = this.counts.replace(value.getName(), delta); + if (old != null) { + delta = delta - old; + } + else { + this.counts.putIfAbsent(value.getName(), delta); + } + return new Delta(value.getName(), delta, value.getTimestamp()); } } diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/export/PrefixMetricGroupExporterTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/export/PrefixMetricGroupExporterTests.java index 5dcd4ff3e90..8f5f8eb5d5b 100644 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/export/PrefixMetricGroupExporterTests.java +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/export/PrefixMetricGroupExporterTests.java @@ -24,6 +24,7 @@ import org.junit.Test; import org.springframework.boot.actuate.metrics.Iterables; import org.springframework.boot.actuate.metrics.Metric; import org.springframework.boot.actuate.metrics.repository.InMemoryMetricRepository; +import org.springframework.boot.actuate.metrics.writer.Delta; import static org.assertj.core.api.Assertions.assertThat; @@ -50,6 +51,15 @@ public class PrefixMetricGroupExporterTests { assertThat(Iterables.collection(this.writer.groups())).hasSize(1); } + @Test + public void countersIncremented() { + this.writer.increment("counter.foo", new Delta("bar", 1L)); + this.reader.set(new Metric("counter.foo.bar", 1)); + this.exporter.setGroups(Collections.singleton("counter.foo")); + this.exporter.export(); + assertThat(this.writer.findAll("counter.foo").iterator().next().getValue()).isEqualTo(2L); + } + @Test public void unprefixedMetricsNotCopied() { this.reader.set(new Metric("foo.bar", 2.3));