diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/MetricRepositoryAutoConfiguration.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/MetricRepositoryAutoConfiguration.java index 3cb66f440c0..ca4e123c829 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/MetricRepositoryAutoConfiguration.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/MetricRepositoryAutoConfiguration.java @@ -28,6 +28,7 @@ import org.springframework.boot.actuate.metrics.buffer.GaugeBuffers; import org.springframework.boot.actuate.metrics.export.Exporter; import org.springframework.boot.actuate.metrics.export.MetricCopyExporter; import org.springframework.boot.actuate.metrics.repository.InMemoryMetricRepository; +import org.springframework.boot.actuate.metrics.repository.InMemoryMultiMetricRepository; import org.springframework.boot.actuate.metrics.writer.DefaultCounterService; import org.springframework.boot.actuate.metrics.writer.DefaultGaugeService; import org.springframework.boot.actuate.metrics.writer.MetricWriter; @@ -154,6 +155,13 @@ public class MetricRepositoryAutoConfiguration { return new InMemoryMetricRepository(); } + @Bean + @ExportMetricReader + @ActuatorMetricWriter + public InMemoryMultiMetricRepository actuatorMultiMetricRepository() { + return new InMemoryMultiMetricRepository(actuatorMetricRepository()); + } + } } diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/repository/InMemoryMetricRepository.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/repository/InMemoryMetricRepository.java index ecd3a48156b..8e5d7b82203 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/repository/InMemoryMetricRepository.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/repository/InMemoryMetricRepository.java @@ -16,10 +16,7 @@ package org.springframework.boot.actuate.metrics.repository; -import java.util.Collection; -import java.util.Collections; import java.util.Date; -import java.util.HashSet; import java.util.concurrent.ConcurrentNavigableMap; import org.springframework.boot.actuate.metrics.Metric; @@ -28,17 +25,15 @@ import org.springframework.boot.actuate.metrics.util.SimpleInMemoryRepository.Ca import org.springframework.boot.actuate.metrics.writer.Delta; /** - * {@link MetricRepository} and {@link MultiMetricRepository} implementation that stores - * metrics in memory. + * {@link MetricRepository} implementation that stores metrics in memory. * * @author Dave Syer + * @author Stephane Nicoll */ -public class InMemoryMetricRepository implements MetricRepository, MultiMetricRepository { +public class InMemoryMetricRepository implements MetricRepository { private final SimpleInMemoryRepository> metrics = new SimpleInMemoryRepository>(); - private final Collection groups = new HashSet(); - public void setValues(ConcurrentNavigableMap> values) { this.metrics.setValues(values); } @@ -52,12 +47,11 @@ public class InMemoryMetricRepository implements MetricRepository, MultiMetricRe @Override public Metric modify(Metric current) { if (current != null) { - Metric metric = current; return new Metric(metricName, - metric.increment(amount).getValue(), timestamp); + current.increment(amount).getValue(), timestamp); } else { - return new Metric(metricName, Long.valueOf(amount), timestamp); + return new Metric(metricName, (long) amount, timestamp); } } }); @@ -68,51 +62,11 @@ public class InMemoryMetricRepository implements MetricRepository, MultiMetricRe this.metrics.set(value.getName(), value); } - @Override - public void set(String group, Collection> values) { - String prefix = group; - if (!prefix.endsWith(".")) { - prefix = prefix + "."; - } - for (Metric metric : values) { - if (!metric.getName().startsWith(prefix)) { - metric = new Metric(prefix + metric.getName(), metric.getValue(), - metric.getTimestamp()); - } - set(metric); - } - this.groups.add(group); - } - - @Override - public void increment(String group, Delta delta) { - String prefix = group; - if (!prefix.endsWith(".")) { - prefix = prefix + "."; - } - if (!delta.getName().startsWith(prefix)) { - delta = new Delta(prefix + delta.getName(), delta.getValue(), - delta.getTimestamp()); - } - increment(delta); - this.groups.add(group); - } - - @Override - public Iterable groups() { - return Collections.unmodifiableCollection(this.groups); - } - @Override public long count() { return this.metrics.count(); } - @Override - public long countGroups() { - return this.groups.size(); - } - @Override public void reset(String metricName) { this.metrics.remove(metricName); @@ -128,9 +82,8 @@ public class InMemoryMetricRepository implements MetricRepository, MultiMetricRe return this.metrics.findAll(); } - @Override - public Iterable> findAll(String metricNamePrefix) { - return this.metrics.findAllWithPrefix(metricNamePrefix); + public Iterable> findAllWithPrefix(String prefix) { + return this.metrics.findAllWithPrefix(prefix); } } diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/repository/InMemoryMultiMetricRepository.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/repository/InMemoryMultiMetricRepository.java new file mode 100644 index 00000000000..e3a4640fc46 --- /dev/null +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/repository/InMemoryMultiMetricRepository.java @@ -0,0 +1,100 @@ +/* + * Copyright 2012-2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.actuate.metrics.repository; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; + +import org.springframework.boot.actuate.metrics.Metric; +import org.springframework.boot.actuate.metrics.writer.Delta; + +/** + * {@link MultiMetricRepository} implementation backed by a + * {@link InMemoryMetricRepository}. + * + * @author Stephane Nicoll + * @since 1.5.0 + */ +public class InMemoryMultiMetricRepository implements MultiMetricRepository { + + private final InMemoryMetricRepository repository; + + private final Collection groups = new HashSet(); + + public InMemoryMultiMetricRepository(InMemoryMetricRepository repository) { + this.repository = repository; + } + + public InMemoryMultiMetricRepository() { + this(new InMemoryMetricRepository()); + } + + @Override + public void set(String group, Collection> values) { + String prefix = group; + if (!prefix.endsWith(".")) { + prefix = prefix + "."; + } + for (Metric metric : values) { + if (!metric.getName().startsWith(prefix)) { + metric = new Metric(prefix + metric.getName(), metric.getValue(), + metric.getTimestamp()); + } + this.repository.set(metric); + } + this.groups.add(group); + } + + @Override + public void increment(String group, Delta delta) { + String prefix = group; + if (!prefix.endsWith(".")) { + prefix = prefix + "."; + } + if (!delta.getName().startsWith(prefix)) { + delta = new Delta(prefix + delta.getName(), delta.getValue(), + delta.getTimestamp()); + } + this.repository.increment(delta); + this.groups.add(group); + } + + @Override + public Iterable groups() { + return Collections.unmodifiableCollection(this.groups); + } + + @Override + public long countGroups() { + return this.groups.size(); + } + + @Override + public void reset(String group) { + for (Metric metric : findAll(group)) { + this.repository.reset(metric.getName()); + } + this.groups.remove(group); + } + + @Override + public Iterable> findAll(String metricNamePrefix) { + return this.repository.findAllWithPrefix(metricNamePrefix); + } + +} 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 678ac9ee352..959889c797c 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 @@ -23,7 +23,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.repository.InMemoryMultiMetricRepository; import org.springframework.boot.actuate.metrics.writer.Delta; import static org.assertj.core.api.Assertions.assertThat; @@ -35,17 +35,17 @@ import static org.assertj.core.api.Assertions.assertThat; */ public class PrefixMetricGroupExporterTests { - private final InMemoryMetricRepository reader = new InMemoryMetricRepository(); + private final InMemoryMultiMetricRepository reader = new InMemoryMultiMetricRepository(); - private final InMemoryMetricRepository writer = new InMemoryMetricRepository(); + private final InMemoryMultiMetricRepository writer = new InMemoryMultiMetricRepository(); private final PrefixMetricGroupExporter exporter = new PrefixMetricGroupExporter( this.reader, this.writer); @Test public void prefixedMetricsCopied() { - this.reader.set(new Metric("foo.bar", 2.3)); - this.reader.set(new Metric("foo.spam", 1.3)); + this.reader.set("foo", Arrays.>asList(new Metric("bar", 2.3), + new Metric("spam", 1.3))); this.exporter.setGroups(Collections.singleton("foo")); this.exporter.export(); assertThat(Iterables.collection(this.writer.groups())).hasSize(1); @@ -54,7 +54,8 @@ public class PrefixMetricGroupExporterTests { @Test public void countersIncremented() { this.writer.increment("counter.foo", new Delta("bar", 1L)); - this.reader.set(new Metric("counter.foo.bar", 1)); + this.reader.set("counter", Collections.>singletonList( + 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()) @@ -63,8 +64,9 @@ public class PrefixMetricGroupExporterTests { @Test public void unprefixedMetricsNotCopied() { - this.reader.set(new Metric("foo.bar", 2.3)); - this.reader.set(new Metric("foo.spam", 1.3)); + this.reader.set("foo", Arrays.>asList( + new Metric("foo.bar", 2.3), + new Metric("foo.spam", 1.3))); this.exporter.setGroups(Collections.singleton("bar")); this.exporter.export(); assertThat(Iterables.collection(this.writer.groups())).isEmpty(); @@ -81,9 +83,11 @@ public class PrefixMetricGroupExporterTests { @Test public void onlyPrefixedMetricsCopied() { - this.reader.set(new Metric("foo.bar", 2.3)); - this.reader.set(new Metric("foo.spam", 1.3)); - this.reader.set(new Metric("foobar.spam", 1.3)); + this.reader.set("foo", Arrays.>asList( + new Metric("foo.bar", 2.3), + new Metric("foo.spam", 1.3))); + this.reader.set("foobar", Collections.>singletonList( + new Metric("foobar.spam", 1.3))); this.exporter.setGroups(Collections.singleton("foo")); this.exporter.export(); assertThat(Iterables.collection(this.writer.groups())).hasSize(1); diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/export/RichGaugeExporterTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/export/RichGaugeExporterTests.java index 7a4e61f028b..d77b10ea934 100644 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/export/RichGaugeExporterTests.java +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/export/RichGaugeExporterTests.java @@ -20,7 +20,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.repository.InMemoryMultiMetricRepository; import org.springframework.boot.actuate.metrics.rich.InMemoryRichGaugeRepository; import static org.assertj.core.api.Assertions.assertThat; @@ -34,7 +34,7 @@ public class RichGaugeExporterTests { private final InMemoryRichGaugeRepository reader = new InMemoryRichGaugeRepository(); - private final InMemoryMetricRepository writer = new InMemoryMetricRepository(); + private final InMemoryMultiMetricRepository writer = new InMemoryMultiMetricRepository(); private final RichGaugeExporter exporter = new RichGaugeExporter(this.reader, this.writer); diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/repository/InMemoryPrefixMetricRepositoryTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/repository/InMemoryMultiMetricRepositoryTests.java similarity index 72% rename from spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/repository/InMemoryPrefixMetricRepositoryTests.java rename to spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/repository/InMemoryMultiMetricRepositoryTests.java index 030eaa4d0ec..38214e9971f 100644 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/repository/InMemoryPrefixMetricRepositoryTests.java +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/repository/InMemoryMultiMetricRepositoryTests.java @@ -16,7 +16,9 @@ package org.springframework.boot.actuate.metrics.repository; +import java.util.HashMap; import java.util.HashSet; +import java.util.Map; import java.util.Set; import org.junit.Test; @@ -29,15 +31,16 @@ import static org.assertj.core.api.Assertions.assertThat; /** * @author Dave Syer */ -public class InMemoryPrefixMetricRepositoryTests { +public class InMemoryMultiMetricRepositoryTests { - private final InMemoryMetricRepository repository = new InMemoryMetricRepository(); + private final InMemoryMultiMetricRepository repository = + new InMemoryMultiMetricRepository(); @Test public void registeredPrefixCounted() { - this.repository.increment(new Delta("foo.bar", 1)); - this.repository.increment(new Delta("foo.bar", 1)); - this.repository.increment(new Delta("foo.spam", 1)); + this.repository.increment("foo", new Delta("bar", 1)); + this.repository.increment("foo", new Delta("bar", 1)); + this.repository.increment("foo", new Delta("spam", 1)); Set names = new HashSet(); for (Metric metric : this.repository.findAll("foo")) { names.add(metric.getName()); @@ -48,7 +51,7 @@ public class InMemoryPrefixMetricRepositoryTests { @Test public void prefixWithWildcard() { - this.repository.increment(new Delta("foo.bar", 1)); + this.repository.increment("foo", new Delta("bar", 1)); Set names = new HashSet(); for (Metric metric : this.repository.findAll("foo.*")) { names.add(metric.getName()); @@ -59,7 +62,7 @@ public class InMemoryPrefixMetricRepositoryTests { @Test public void prefixWithPeriod() { - this.repository.increment(new Delta("foo.bar", 1)); + this.repository.increment("foo", new Delta("bar", 1)); Set names = new HashSet(); for (Metric metric : this.repository.findAll("foo.")) { names.add(metric.getName()); @@ -70,8 +73,8 @@ public class InMemoryPrefixMetricRepositoryTests { @Test public void onlyRegisteredPrefixCounted() { - this.repository.increment(new Delta("foo.bar", 1)); - this.repository.increment(new Delta("foobar.spam", 1)); + this.repository.increment("foo", new Delta("bar", 1)); + this.repository.increment("foobar", new Delta("spam", 1)); Set names = new HashSet(); for (Metric metric : this.repository.findAll("foo")) { names.add(metric.getName()); @@ -85,13 +88,13 @@ public class InMemoryPrefixMetricRepositoryTests { this.repository.increment("foo", new Delta("foo.bar", 1)); this.repository.increment("foo", new Delta("foo.bar", 2)); this.repository.increment("foo", new Delta("foo.spam", 1)); - Set names = new HashSet(); + Map> metrics = new HashMap>(); for (Metric metric : this.repository.findAll("foo")) { - names.add(metric.getName()); + metrics.put(metric.getName(), metric); } - assertThat(names).hasSize(2); - assertThat(names.contains("foo.bar")).isTrue(); - assertThat(this.repository.findOne("foo.bar").getValue()).isEqualTo(3L); + assertThat(metrics).hasSize(2); + assertThat(metrics).containsKeys("foo.bar", "foo.spam"); + assertThat(metrics.get("foo.bar").getValue()).isEqualTo(3L); } } diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/rich/MultiMetricRichGaugeReaderTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/rich/MultiMetricRichGaugeReaderTests.java index 3a7afaee1f9..b6b195d808d 100644 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/rich/MultiMetricRichGaugeReaderTests.java +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/rich/MultiMetricRichGaugeReaderTests.java @@ -20,7 +20,7 @@ import org.junit.Test; import org.springframework.boot.actuate.metrics.Metric; import org.springframework.boot.actuate.metrics.export.RichGaugeExporter; -import org.springframework.boot.actuate.metrics.repository.InMemoryMetricRepository; +import org.springframework.boot.actuate.metrics.repository.InMemoryMultiMetricRepository; import static org.assertj.core.api.Assertions.assertThat; @@ -31,7 +31,7 @@ import static org.assertj.core.api.Assertions.assertThat; */ public class MultiMetricRichGaugeReaderTests { - private InMemoryMetricRepository repository = new InMemoryMetricRepository(); + private InMemoryMultiMetricRepository repository = new InMemoryMultiMetricRepository(); private MultiMetricRichGaugeReader reader = new MultiMetricRichGaugeReader( this.repository); @@ -47,7 +47,7 @@ public class MultiMetricRichGaugeReaderTests { this.data.set(new Metric("foo", 1)); this.exporter.export(); // Check the exporter worked - assertThat(this.repository.count()).isEqualTo(6); + assertThat(this.repository.countGroups()).isEqualTo(1); assertThat(this.reader.count()).isEqualTo(1); RichGauge one = this.reader.findOne("foo"); assertThat(one).isNotNull();