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 35a64e4476f..d95654533e9 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 @@ -88,6 +88,11 @@ public class InMemoryMetricRepository implements MetricRepository, MultiMetricRe return this.metrics.count(); } + @Override + public long countGroups() { + return this.groups.size(); + } + @Override public void reset(String metricName) { this.metrics.remove(metricName); diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/repository/MultiMetricRepository.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/repository/MultiMetricRepository.java index ecefafbeaae..fbdb10808e7 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/repository/MultiMetricRepository.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/repository/MultiMetricRepository.java @@ -52,6 +52,6 @@ public interface MultiMetricRepository extends PrefixMetricReader { /** * @return the number of groups available */ - long count(); + long countGroups(); } diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/repository/redis/RedisMultiMetricRepository.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/repository/redis/RedisMultiMetricRepository.java index 3067d0c6bc1..0586345ce56 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/repository/redis/RedisMultiMetricRepository.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/repository/redis/RedisMultiMetricRepository.java @@ -108,7 +108,7 @@ public class RedisMultiMetricRepository implements MultiMetricRepository { } @Override - public long count() { + public long countGroups() { return this.zSetOperations.size(); } diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/rich/MultiMetricRichGaugeReader.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/rich/MultiMetricRichGaugeReader.java new file mode 100644 index 00000000000..ea6156a2343 --- /dev/null +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/rich/MultiMetricRichGaugeReader.java @@ -0,0 +1,96 @@ +/* + * Copyright 2014-2015 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.rich; + +import java.util.ArrayList; +import java.util.List; + +import org.springframework.boot.actuate.metrics.Metric; +import org.springframework.boot.actuate.metrics.repository.MultiMetricRepository; + +/** + * A {@link RichGaugeReader} that works by reading metric values from a + * {@link MultiMetricRepository} where the group name is the RichGauge name. The format + * used matches that in he RichGaugeExporter, so this reader can be used on a store that + * has been populated using that exporter. + * + * @author Dave Syer + * + * @since 1.1.0 + */ +public class MultiMetricRichGaugeReader implements RichGaugeReader { + + private static final String COUNT = ".count"; + private static final String MAX = ".max"; + private static final String MIN = ".min"; + private static final String AVG = ".avg"; + private static final String ALPHA = ".alpha"; + private static final String VAL = ".val"; + + private final MultiMetricRepository repository; + + public MultiMetricRichGaugeReader(MultiMetricRepository repository) { + this.repository = repository; + } + + @Override + public RichGauge findOne(String name) { + Iterable> metrics = this.repository.findAll(name); + double value = 0; + double average = 0.; + double alpha = -1.; + double min = 0.; + double max = 0.; + long count = 0; + for (Metric metric : metrics) { + if (metric.getName().endsWith(VAL)) { + value = metric.getValue().doubleValue(); + } + else if (metric.getName().endsWith(ALPHA)) { + alpha = metric.getValue().doubleValue(); + } + else if (metric.getName().endsWith(AVG)) { + average = metric.getValue().doubleValue(); + } + else if (metric.getName().endsWith(MIN)) { + min = metric.getValue().doubleValue(); + } + else if (metric.getName().endsWith(MAX)) { + max = metric.getValue().doubleValue(); + } + else if (metric.getName().endsWith(COUNT)) { + count = metric.getValue().longValue(); + } + } + return new RichGauge(name, value, alpha, average, max, min, count); + } + + @Override + public Iterable findAll() { + List result = new ArrayList(); + for (String name : this.repository.groups()) { + result.add(findOne(name)); + } + return result; + } + + @Override + public long count() { + return this.repository.countGroups(); + } + +} diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/repository/redis/RedisMultiMetricRepositoryTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/repository/redis/RedisMultiMetricRepositoryTests.java index 0af5c7a8911..e2309def8a9 100644 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/repository/redis/RedisMultiMetricRepositoryTests.java +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/repository/redis/RedisMultiMetricRepositoryTests.java @@ -78,7 +78,7 @@ public class RedisMultiMetricRepositoryTests { "foo.val", 12.3), new Metric("foo.bar", 11.3))); this.repository.save("bar", Arrays.> asList(new Metric( "bar.val", 12.3), new Metric("bar.foo", 11.3))); - assertEquals(2, this.repository.count()); + assertEquals(2, this.repository.countGroups()); } } 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 new file mode 100644 index 00000000000..1624b020742 --- /dev/null +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/rich/MultiMetricRichGaugeReaderTests.java @@ -0,0 +1,62 @@ +/* + * Copyright 2012-2013 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.rich; + +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 static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +/** + * @author Dave Syer + */ +public class MultiMetricRichGaugeReaderTests { + + private InMemoryMetricRepository repository = new InMemoryMetricRepository(); + private MultiMetricRichGaugeReader reader = new MultiMetricRichGaugeReader( + this.repository); + private InMemoryRichGaugeRepository data = new InMemoryRichGaugeRepository(); + private RichGaugeExporter exporter = new RichGaugeExporter(this.data, this.repository); + + @Test + public void countOne() { + this.data.set(new Metric("foo", 1)); + this.data.set(new Metric("foo", 1)); + this.exporter.export(); + // Check the exporter worked + assertEquals(6, this.repository.count()); + assertEquals(1, this.reader.count()); + RichGauge one = this.reader.findOne("foo"); + assertNotNull(one); + assertEquals(2, one.getCount()); + } + + @Test + public void countTwo() { + this.data.set(new Metric("foo", 1)); + this.data.set(new Metric("bar", 1)); + this.exporter.export(); + assertEquals(2, this.reader.count()); + RichGauge one = this.reader.findOne("foo"); + assertNotNull(one); + assertEquals(1, one.getCount()); + } + +} diff --git a/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java b/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java index 735eb0405f9..f96a7134b1d 100644 --- a/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java +++ b/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java @@ -1014,9 +1014,9 @@ public class SpringApplication { } } - private static Set asUnmodifiableOrderedSet(Collection elemements) { + private static Set asUnmodifiableOrderedSet(Collection elements) { List list = new ArrayList(); - list.addAll(elemements); + list.addAll(elements); Collections.sort(list, AnnotationAwareOrderComparator.INSTANCE); return new LinkedHashSet(list); }