Commit 5f6698e5 authored by Phillip Webb's avatar Phillip Webb

Merge pull request #14497 from pulkitmehra

* pr/14497:
  Polish "Stop MetricsEndpoint from summing up same metrics"
  Stop MetricsEndpoint from summing up same metrics
parents 2a2908e7 30ab4f96
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
package org.springframework.boot.actuate.metrics; package org.springframework.boot.actuate.metrics;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
...@@ -81,15 +82,15 @@ public class MetricsEndpoint { ...@@ -81,15 +82,15 @@ public class MetricsEndpoint {
public MetricResponse metric(@Selector String requiredMetricName, public MetricResponse metric(@Selector String requiredMetricName,
@Nullable List<String> tag) { @Nullable List<String> tag) {
List<Tag> tags = parseTags(tag); List<Tag> tags = parseTags(tag);
List<Meter> meters = new ArrayList<>(); Collection<Meter> meters = findFirstMatchingMeters(this.registry,
collectMeters(meters, this.registry, requiredMetricName, tags); requiredMetricName, tags);
if (meters.isEmpty()) { if (meters.isEmpty()) {
return null; return null;
} }
Map<Statistic, Double> samples = getSamples(meters); Map<Statistic, Double> samples = getSamples(meters);
Map<String, Set<String>> availableTags = getAvailableTags(meters); Map<String, Set<String>> availableTags = getAvailableTags(meters);
tags.forEach((t) -> availableTags.remove(t.getKey())); tags.forEach((t) -> availableTags.remove(t.getKey()));
Meter.Id meterId = meters.get(0).getId(); Meter.Id meterId = meters.iterator().next().getId();
return new MetricResponse(requiredMetricName, meterId.getDescription(), return new MetricResponse(requiredMetricName, meterId.getDescription(),
meterId.getBaseUnit(), asList(samples, Sample::new), meterId.getBaseUnit(), asList(samples, Sample::new),
asList(availableTags, AvailableTag::new)); asList(availableTags, AvailableTag::new));
...@@ -112,18 +113,23 @@ public class MetricsEndpoint { ...@@ -112,18 +113,23 @@ public class MetricsEndpoint {
return Tag.of(parts[0], parts[1]); return Tag.of(parts[0], parts[1]);
} }
private void collectMeters(List<Meter> meters, MeterRegistry registry, String name, private Collection<Meter> findFirstMatchingMeters(MeterRegistry registry, String name,
Iterable<Tag> tags) { Iterable<Tag> tags) {
if (registry instanceof CompositeMeterRegistry) { if (registry instanceof CompositeMeterRegistry) {
((CompositeMeterRegistry) registry).getRegistries() return findFirstMatchingMeters((CompositeMeterRegistry) registry, name, tags);
.forEach((member) -> collectMeters(meters, member, name, tags));
}
else {
meters.addAll(registry.find(name).tags(tags).meters());
} }
return registry.find(name).tags(tags).meters();
}
private Collection<Meter> findFirstMatchingMeters(CompositeMeterRegistry composite,
String name, Iterable<Tag> tags) {
return composite.getRegistries().stream()
.map((registry) -> findFirstMatchingMeters(registry, name, tags))
.filter((matching) -> !matching.isEmpty()).findFirst()
.orElse(Collections.emptyList());
} }
private Map<Statistic, Double> getSamples(List<Meter> meters) { private Map<Statistic, Double> getSamples(Collection<Meter> meters) {
Map<Statistic, Double> samples = new LinkedHashMap<>(); Map<Statistic, Double> samples = new LinkedHashMap<>();
meters.forEach((meter) -> mergeMeasurements(samples, meter)); meters.forEach((meter) -> mergeMeasurements(samples, meter));
return samples; return samples;
...@@ -138,7 +144,7 @@ public class MetricsEndpoint { ...@@ -138,7 +144,7 @@ public class MetricsEndpoint {
return Statistic.MAX.equals(statistic) ? Double::max : Double::sum; return Statistic.MAX.equals(statistic) ? Double::max : Double::sum;
} }
private Map<String, Set<String>> getAvailableTags(List<Meter> meters) { private Map<String, Set<String>> getAvailableTags(Collection<Meter> meters) {
Map<String, Set<String>> availableTags = new HashMap<>(); Map<String, Set<String>> availableTags = new HashMap<>();
meters.forEach((meter) -> mergeAvailableTags(availableTags, meter)); meters.forEach((meter) -> mergeAvailableTags(availableTags, meter));
return availableTags; return availableTags;
......
...@@ -95,6 +95,42 @@ public class MetricsEndpointTests { ...@@ -95,6 +95,42 @@ public class MetricsEndpointTests {
assertThat(getCount(response)).hasValue(4.0); assertThat(getCount(response)).hasValue(4.0);
} }
@Test
public void findFirstMatchingMetersFromNestedRegistries() {
CompositeMeterRegistry composite = new CompositeMeterRegistry();
SimpleMeterRegistry firstLevel0 = new SimpleMeterRegistry();
CompositeMeterRegistry firstLevel1 = new CompositeMeterRegistry();
SimpleMeterRegistry secondLevel = new SimpleMeterRegistry();
composite.add(firstLevel0);
composite.add(firstLevel1);
firstLevel1.add(secondLevel);
secondLevel.counter("cache", "result", "hit", "host", "1").increment(2);
secondLevel.counter("cache", "result", "miss", "host", "1").increment(2);
secondLevel.counter("cache", "result", "hit", "host", "2").increment(2);
MetricsEndpoint endpoint = new MetricsEndpoint(composite);
MetricsEndpoint.MetricResponse response = endpoint.metric("cache",
Collections.emptyList());
assertThat(response.getName()).isEqualTo("cache");
assertThat(availableTagKeys(response)).containsExactly("result", "host");
assertThat(getCount(response)).hasValue(6.0);
response = endpoint.metric("cache", Collections.singletonList("result:hit"));
assertThat(availableTagKeys(response)).containsExactly("host");
assertThat(getCount(response)).hasValue(4.0);
}
@Test
public void matchingMeterNotFoundInNestedRegistries() {
CompositeMeterRegistry composite = new CompositeMeterRegistry();
CompositeMeterRegistry firstLevel = new CompositeMeterRegistry();
SimpleMeterRegistry secondLevel = new SimpleMeterRegistry();
composite.add(firstLevel);
firstLevel.add(secondLevel);
MetricsEndpoint endpoint = new MetricsEndpoint(composite);
MetricsEndpoint.MetricResponse response = endpoint.metric("invalid.metric.name",
Collections.emptyList());
assertThat(response).isNull();
}
@Test @Test
public void metricTagValuesAreDeduplicated() { public void metricTagValuesAreDeduplicated() {
this.registry.counter("cache", "host", "1", "region", "east", "result", "hit"); this.registry.counter("cache", "host", "1", "region", "east", "result", "hit");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment