From 918ad8b710e04e9df4369162d4f6105a42cd3cf7 Mon Sep 17 00:00:00 2001 From: Jon Schneider Date: Tue, 5 Sep 2017 13:46:04 -0500 Subject: [PATCH] Fix Atlas percentiles tags * Polish on Spring configuration * Move scripts to start various monitoring systems to /scripts --- .../SpectatorDistributionSummary.java | 2 +- .../spectator/SpectatorMeterRegistry.java | 6 +- .../instrument/spectator/SpectatorTimer.java | 2 +- .../core/instrument/stats/hist/Bucket.java | 14 +++-- .../stats/hist/DefaultHistogramBuilder.java | 13 +++- .../core/instrument/stats/hist/Histogram.java | 22 +++++-- .../hist/TimeScalingHistogramBuilder.java | 13 +++- .../spring/MetricsConfiguration.java | 6 +- ...spect.java => ScheduledMethodMetrics.java} | 6 +- .../spring/web/ControllerMetrics.java | 4 +- .../MetricsServletRequestConfiguration.java | 8 +-- ...urer.java => WebServletTagConfigurer.java} | 26 +++++--- .../samples/components/PersonController.java | 2 +- .../src/samples/resources/application.yml | 5 +- .../spring/MetricsConfigurationTest.java | 2 +- ...t.java => ScheduledMethodMetricsTest.java} | 2 +- .../src/samples => scripts}/.gitignore | 0 .../src/samples => scripts}/README.md | 0 .../src/samples => scripts}/atlas.sh | 0 .../src/samples => scripts}/ganglia.sh | 0 .../src/samples => scripts}/graphite.sh | 0 .../src/samples => scripts}/influx.sh | 0 .../src/samples => scripts}/prometheus.sh | 0 .../micrometer/atlas/AtlasMeterRegistry.java | 61 +++++++++++++++++-- 24 files changed, 145 insertions(+), 49 deletions(-) rename micrometer-spring-legacy/src/main/java/io/micrometer/spring/scheduling/{MetricsSchedulingAspect.java => ScheduledMethodMetrics.java} (95%) rename micrometer-spring-legacy/src/main/java/io/micrometer/spring/web/{WebmvcTagConfigurer.java => WebServletTagConfigurer.java} (79%) rename micrometer-spring-legacy/src/test/java/io/micrometer/spring/scheduling/{MetricsSchedulingAspectTest.java => ScheduledMethodMetricsTest.java} (99%) rename {micrometer-spring-legacy/src/samples => scripts}/.gitignore (100%) rename {micrometer-spring-legacy/src/samples => scripts}/README.md (100%) rename {micrometer-spring-legacy/src/samples => scripts}/atlas.sh (100%) rename {micrometer-spring-legacy/src/samples => scripts}/ganglia.sh (100%) rename {micrometer-spring-legacy/src/samples => scripts}/graphite.sh (100%) rename {micrometer-spring-legacy/src/samples => scripts}/influx.sh (100%) rename {micrometer-spring-legacy/src/samples => scripts}/prometheus.sh (100%) diff --git a/micrometer-core/src/main/java/io/micrometer/core/instrument/spectator/SpectatorDistributionSummary.java b/micrometer-core/src/main/java/io/micrometer/core/instrument/spectator/SpectatorDistributionSummary.java index 10447e1d98..4ccd30a392 100644 --- a/micrometer-core/src/main/java/io/micrometer/core/instrument/spectator/SpectatorDistributionSummary.java +++ b/micrometer-core/src/main/java/io/micrometer/core/instrument/spectator/SpectatorDistributionSummary.java @@ -26,7 +26,7 @@ public class SpectatorDistributionSummary extends AbstractMeter implements Distr private final Quantiles quantiles; private final Histogram histogram; - SpectatorDistributionSummary(Id id, String description, + public SpectatorDistributionSummary(Id id, String description, com.netflix.spectator.api.DistributionSummary distributionSummary, Quantiles quantiles, Histogram histogram) { diff --git a/micrometer-core/src/main/java/io/micrometer/core/instrument/spectator/SpectatorMeterRegistry.java b/micrometer-core/src/main/java/io/micrometer/core/instrument/spectator/SpectatorMeterRegistry.java index 53799cbe25..564605d188 100644 --- a/micrometer-core/src/main/java/io/micrometer/core/instrument/spectator/SpectatorMeterRegistry.java +++ b/micrometer-core/src/main/java/io/micrometer/core/instrument/spectator/SpectatorMeterRegistry.java @@ -44,7 +44,7 @@ public SpectatorMeterRegistry(Registry registry, Clock clock) { this.registry = registry; } - private Collection toSpectatorTags(Iterable tags) { + protected Collection toSpectatorTags(Iterable tags) { return stream(tags.spliterator(), false) .map(t -> new BasicTag(t.getKey(), t.getValue())) .collect(toList()); @@ -88,7 +88,7 @@ protected io.micrometer.core.instrument.Gauge newGauge(Meter.Id id, String d return new SpectatorGauge(id, description, gauge); } - private Histogram registerHistogramCounterIfNecessary(Meter.Id id, Histogram.Builder histogramBuilder) { + protected Histogram registerHistogramCounterIfNecessary(Meter.Id id, Histogram.Builder histogramBuilder) { if (histogramBuilder != null) { return histogramBuilder .bucketListener(bucket -> { @@ -100,7 +100,7 @@ private Histogram registerHistogramCounterIfNecessary(Meter.Id id, Histogram. return null; } - private void registerQuantilesGaugeIfNecessary(Meter.Id id, Quantiles quantiles, UnaryOperator scaling) { + protected void registerQuantilesGaugeIfNecessary(Meter.Id id, Quantiles quantiles, UnaryOperator scaling) { if (quantiles != null) { for (Double q : quantiles.monitored()) { if (!Double.isNaN(q)) { diff --git a/micrometer-core/src/main/java/io/micrometer/core/instrument/spectator/SpectatorTimer.java b/micrometer-core/src/main/java/io/micrometer/core/instrument/spectator/SpectatorTimer.java index f9dfbf44cc..c89e873d8a 100644 --- a/micrometer-core/src/main/java/io/micrometer/core/instrument/spectator/SpectatorTimer.java +++ b/micrometer-core/src/main/java/io/micrometer/core/instrument/spectator/SpectatorTimer.java @@ -29,7 +29,7 @@ public class SpectatorTimer extends AbstractTimer { private final Quantiles quantiles; private final Histogram histogram; - SpectatorTimer(Id id, String description, Timer timer, + public SpectatorTimer(Id id, String description, Timer timer, Clock clock, Quantiles quantiles, Histogram histogram) { super(id, description, clock); this.timer = timer; diff --git a/micrometer-core/src/main/java/io/micrometer/core/instrument/stats/hist/Bucket.java b/micrometer-core/src/main/java/io/micrometer/core/instrument/stats/hist/Bucket.java index 19fe9cb1c0..fe6238fa3d 100644 --- a/micrometer-core/src/main/java/io/micrometer/core/instrument/stats/hist/Bucket.java +++ b/micrometer-core/src/main/java/io/micrometer/core/instrument/stats/hist/Bucket.java @@ -21,6 +21,11 @@ public class Bucket { private final T tag; + /** + * {@code true} if this bucket is used in an aggregable percentile approximation. + */ + private final boolean percentile; + /** * Cached string representation of {@code tag}. */ @@ -28,13 +33,14 @@ public class Bucket { LongAdder value = new LongAdder(); - public Bucket(T tag) { + public Bucket(T tag, boolean percentile, long initialValue) { this.tag = tag; + this.percentile = percentile; + this.value.add(initialValue); } - public Bucket(T tag, long initialValue) { - this.tag = tag; - this.value.add(initialValue); + public boolean isPercentile() { + return percentile; } public String getTag() { diff --git a/micrometer-core/src/main/java/io/micrometer/core/instrument/stats/hist/DefaultHistogramBuilder.java b/micrometer-core/src/main/java/io/micrometer/core/instrument/stats/hist/DefaultHistogramBuilder.java index d7f3171d31..e934bde4b6 100644 --- a/micrometer-core/src/main/java/io/micrometer/core/instrument/stats/hist/DefaultHistogramBuilder.java +++ b/micrometer-core/src/main/java/io/micrometer/core/instrument/stats/hist/DefaultHistogramBuilder.java @@ -23,6 +23,7 @@ class DefaultHistogramBuilder implements Histogram.Builder { private final BucketFunction f; private Histogram.Type type = null; private List> bucketListeners = new ArrayList<>(); + private boolean percentiles = false; DefaultHistogramBuilder(BucketFunction f) { this.f = f; @@ -30,18 +31,24 @@ class DefaultHistogramBuilder implements Histogram.Builder { @Override public Histogram create(TimeUnit baseTimeUnit, Histogram.Type defaultType) { - return new Histogram<>(f, type == null ? defaultType : type, bucketListeners); + return new Histogram<>(f, type == null ? defaultType : type, bucketListeners, percentiles); } @Override - public Histogram.Builder bucketListener(BucketListener listener) { + public Histogram.Builder bucketListener(BucketListener listener) { bucketListeners.add(listener); return this; } @Override - public Histogram.Builder type(Histogram.Type type) { + public Histogram.Builder type(Histogram.Type type) { this.type = type; return this; } + + @Override + public Histogram.Builder usedForPercentiles() { + this.percentiles = true; + return this; + } } diff --git a/micrometer-core/src/main/java/io/micrometer/core/instrument/stats/hist/Histogram.java b/micrometer-core/src/main/java/io/micrometer/core/instrument/stats/hist/Histogram.java index b089e3195e..b21d5c3f8f 100644 --- a/micrometer-core/src/main/java/io/micrometer/core/instrument/stats/hist/Histogram.java +++ b/micrometer-core/src/main/java/io/micrometer/core/instrument/stats/hist/Histogram.java @@ -26,11 +26,13 @@ public class Histogram { private final BucketFunction f; private final Type type; private final List> bucketListeners; + private final boolean percentiles; - public Histogram(BucketFunction f, Type type, List> listeners) { + public Histogram(BucketFunction f, Type type, List> listeners, boolean percentiles) { this.f = f; this.type = type; this.bucketListeners = listeners; + this.percentiles = percentiles; } public Collection> getBuckets() { @@ -41,6 +43,10 @@ public boolean isCumulative() { return type.equals(Type.Cumulative); } + public boolean isPercentiles() { + return percentiles; + } + public Type getType() { return type; } @@ -65,6 +71,12 @@ public interface Builder { * Set the histogram type explicitly, overriding the monitoring system's default histogram type. */ Builder type(Type type); + + /** + * Hacky, but Atlas :percentiles math requires a different tag key than what we would place on + * an ordinary histogram + */ + Builder usedForPercentiles(); } public static Builder function(BucketFunction f) { @@ -114,11 +126,11 @@ public static Builder exponentialTime(TimeUnit unit, double start, doubl } public static Builder percentiles() { - return new DefaultHistogramBuilder<>(percentilesFunction()); + return new DefaultHistogramBuilder<>(percentilesFunction()).usedForPercentiles(); } public static Builder percentilesTime() { - return new TimeScalingHistogramBuilder(percentilesFunction(), TimeUnit.NANOSECONDS); + return new TimeScalingHistogramBuilder(percentilesFunction(), TimeUnit.NANOSECONDS).usedForPercentiles(); } private static BucketFunction percentilesFunction() { @@ -160,8 +172,8 @@ public void observe(double value) { if (isCumulative()) { Map.Entry> ceiling = buckets.ceilingEntry(tag); - bucket = new Bucket<>(tag, ceiling == null ? 1 : ceiling.getValue().getValue() + 1); - } else bucket = new Bucket<>(tag, 1); + bucket = new Bucket<>(tag, percentiles, ceiling == null ? 1 : ceiling.getValue().getValue() + 1); + } else bucket = new Bucket<>(tag, percentiles, 1); bucketListeners.forEach(listener -> listener.bucketAdded(bucket)); diff --git a/micrometer-core/src/main/java/io/micrometer/core/instrument/stats/hist/TimeScalingHistogramBuilder.java b/micrometer-core/src/main/java/io/micrometer/core/instrument/stats/hist/TimeScalingHistogramBuilder.java index afef2ff6cd..871ff730bb 100644 --- a/micrometer-core/src/main/java/io/micrometer/core/instrument/stats/hist/TimeScalingHistogramBuilder.java +++ b/micrometer-core/src/main/java/io/micrometer/core/instrument/stats/hist/TimeScalingHistogramBuilder.java @@ -26,6 +26,7 @@ class TimeScalingHistogramBuilder implements Histogram.Builder { private final TimeUnit fUnits; private Histogram.Type type = null; private List> bucketListeners = new ArrayList<>(); + private boolean percentiles = false; TimeScalingHistogramBuilder(BucketFunction f, TimeUnit fUnits) { this.f = f; @@ -34,17 +35,17 @@ class TimeScalingHistogramBuilder implements Histogram.Builder { @Override public Histogram create(TimeUnit baseTimeUnit, Histogram.Type defaultType) { - return new Histogram<>(timeScale(f, baseTimeUnit), type == null ? defaultType : type, bucketListeners); + return new Histogram<>(timeScale(f, baseTimeUnit), type == null ? defaultType : type, bucketListeners, percentiles); } @Override - public Histogram.Builder type(Histogram.Type type) { + public Histogram.Builder type(Histogram.Type type) { this.type = type; return this; } @Override - public Histogram.Builder bucketListener(BucketListener listener) { + public Histogram.Builder bucketListener(BucketListener listener) { bucketListeners.add(listener); return this; } @@ -55,4 +56,10 @@ private BucketFunction timeScale(BucketFunction f, TimeUnit base return TimeUtils.convert(unscaledBucket, fUnits, baseTimeUnit); }; } + + @Override + public Histogram.Builder usedForPercentiles() { + this.percentiles = true; + return this; + } } diff --git a/micrometer-spring-legacy/src/main/java/io/micrometer/spring/MetricsConfiguration.java b/micrometer-spring-legacy/src/main/java/io/micrometer/spring/MetricsConfiguration.java index bb40f06ce3..654a4b4f2a 100644 --- a/micrometer-spring-legacy/src/main/java/io/micrometer/spring/MetricsConfiguration.java +++ b/micrometer-spring-legacy/src/main/java/io/micrometer/spring/MetricsConfiguration.java @@ -28,7 +28,7 @@ import io.micrometer.spring.export.influx.InfluxExportConfiguration; import io.micrometer.spring.export.jmx.JmxExportConfiguration; import io.micrometer.spring.export.prometheus.PrometheusExportConfiguration; -import io.micrometer.spring.scheduling.MetricsSchedulingAspect; +import io.micrometer.spring.scheduling.ScheduledMethodMetrics; import io.micrometer.spring.web.MetricsRestTemplateConfiguration; import io.micrometer.spring.web.MetricsServletRequestConfiguration; import org.springframework.beans.factory.ObjectProvider; @@ -104,8 +104,8 @@ public MeterRegistryConfigurationSupport(MeterRegistry registry, @Bean @ConditionalOnClass(name = "org.aspectj.lang.ProceedingJoinPoint") @ConditionalOnProperty(value = "spring.aop.enabled", havingValue = "true", matchIfMissing = true) - public MetricsSchedulingAspect metricsSchedulingAspect(MeterRegistry registry) { - return new MetricsSchedulingAspect(registry); + public ScheduledMethodMetrics metricsSchedulingAspect(MeterRegistry registry) { + return new ScheduledMethodMetrics(registry); } @Configuration diff --git a/micrometer-spring-legacy/src/main/java/io/micrometer/spring/scheduling/MetricsSchedulingAspect.java b/micrometer-spring-legacy/src/main/java/io/micrometer/spring/scheduling/ScheduledMethodMetrics.java similarity index 95% rename from micrometer-spring-legacy/src/main/java/io/micrometer/spring/scheduling/MetricsSchedulingAspect.java rename to micrometer-spring-legacy/src/main/java/io/micrometer/spring/scheduling/ScheduledMethodMetrics.java index b0e4928fc8..e0a12d6bf5 100644 --- a/micrometer-spring-legacy/src/main/java/io/micrometer/spring/scheduling/MetricsSchedulingAspect.java +++ b/micrometer-spring-legacy/src/main/java/io/micrometer/spring/scheduling/ScheduledMethodMetrics.java @@ -32,12 +32,12 @@ import java.util.concurrent.TimeUnit; @Aspect -public class MetricsSchedulingAspect { - private static final Log logger = LogFactory.getLog(MetricsSchedulingAspect.class); +public class ScheduledMethodMetrics { + private static final Log logger = LogFactory.getLog(ScheduledMethodMetrics.class); private final MeterRegistry registry; - public MetricsSchedulingAspect(MeterRegistry registry) { + public ScheduledMethodMetrics(MeterRegistry registry) { this.registry = registry; } diff --git a/micrometer-spring-legacy/src/main/java/io/micrometer/spring/web/ControllerMetrics.java b/micrometer-spring-legacy/src/main/java/io/micrometer/spring/web/ControllerMetrics.java index 89d50a0b74..b59a665d18 100644 --- a/micrometer-spring-legacy/src/main/java/io/micrometer/spring/web/ControllerMetrics.java +++ b/micrometer-spring-legacy/src/main/java/io/micrometer/spring/web/ControllerMetrics.java @@ -49,13 +49,13 @@ public class ControllerMetrics { private final MeterRegistry registry; private MetricsConfigurationProperties properties; - private final WebmvcTagConfigurer tagConfigurer; + private final WebServletTagConfigurer tagConfigurer; private final Map longTaskTimerIds = Collections.synchronizedMap(new IdentityHashMap<>()); public ControllerMetrics(MeterRegistry registry, MetricsConfigurationProperties properties, - WebmvcTagConfigurer tagConfigurer) { + WebServletTagConfigurer tagConfigurer) { this.registry = registry; this.properties = properties; this.tagConfigurer = tagConfigurer; diff --git a/micrometer-spring-legacy/src/main/java/io/micrometer/spring/web/MetricsServletRequestConfiguration.java b/micrometer-spring-legacy/src/main/java/io/micrometer/spring/web/MetricsServletRequestConfiguration.java index e3c560ae65..f823bc5a74 100644 --- a/micrometer-spring-legacy/src/main/java/io/micrometer/spring/web/MetricsServletRequestConfiguration.java +++ b/micrometer-spring-legacy/src/main/java/io/micrometer/spring/web/MetricsServletRequestConfiguration.java @@ -36,15 +36,15 @@ @EnableConfigurationProperties(MetricsConfigurationProperties.class) public class MetricsServletRequestConfiguration extends WebMvcConfigurerAdapter { @Bean - @ConditionalOnMissingBean(WebmvcTagConfigurer.class) - WebmvcTagConfigurer webmvcTagConfigurer() { - return new WebmvcTagConfigurer(); + @ConditionalOnMissingBean(WebServletTagConfigurer.class) + WebServletTagConfigurer webmvcTagConfigurer() { + return new WebServletTagConfigurer(); } @Bean ControllerMetrics controllerMetrics(MeterRegistry registry, MetricsConfigurationProperties properties, - WebmvcTagConfigurer configurer) { + WebServletTagConfigurer configurer) { return new ControllerMetrics(registry, properties, configurer); } diff --git a/micrometer-spring-legacy/src/main/java/io/micrometer/spring/web/WebmvcTagConfigurer.java b/micrometer-spring-legacy/src/main/java/io/micrometer/spring/web/WebServletTagConfigurer.java similarity index 79% rename from micrometer-spring-legacy/src/main/java/io/micrometer/spring/web/WebmvcTagConfigurer.java rename to micrometer-spring-legacy/src/main/java/io/micrometer/spring/web/WebServletTagConfigurer.java index 36765622a1..bb18b55f3f 100644 --- a/micrometer-spring-legacy/src/main/java/io/micrometer/spring/web/WebmvcTagConfigurer.java +++ b/micrometer-spring-legacy/src/main/java/io/micrometer/spring/web/WebServletTagConfigurer.java @@ -1,12 +1,12 @@ /** * Copyright 2017 Pivotal Software, Inc. - * + *

* 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 - * + *

+ * 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. @@ -29,7 +29,9 @@ * * @author Jon Schneider */ -public class WebmvcTagConfigurer { +public class WebServletTagConfigurer { + public static WebServletTagConfigurer DEFAULT = new WebServletTagConfigurer(); + /** * Supplies default tags to long task timers. * @@ -50,11 +52,21 @@ public Iterable httpLongRequestTags(HttpServletRequest request, Object hand * @return A set of tags added to every Spring MVC HTTP request. */ public Iterable httpRequestTags(HttpServletRequest request, - HttpServletResponse response, - Throwable ex) { + HttpServletResponse response, + Throwable ex) { + return defaultHttpRequestTags(request, response, ex); + } + + private Iterable defaultHttpRequestTags(HttpServletRequest request, + HttpServletResponse response, + Throwable ex) { return asList(method(request), uri(request), exception(ex), status(response)); } + private Iterable defaultHttpLongRequestTags(HttpServletRequest request, Object handler) { + return asList(method(request), uri(request)); + } + /** * @param request The HTTP request. * @return A "method" tag whose value is a capitalized method (e.g. GET). diff --git a/micrometer-spring-legacy/src/samples/java/io/micrometer/spring/samples/components/PersonController.java b/micrometer-spring-legacy/src/samples/java/io/micrometer/spring/samples/components/PersonController.java index 9ee9afd352..d81796c645 100644 --- a/micrometer-spring-legacy/src/samples/java/io/micrometer/spring/samples/components/PersonController.java +++ b/micrometer-spring-legacy/src/samples/java/io/micrometer/spring/samples/components/PersonController.java @@ -27,7 +27,7 @@ public class PersonController { private List people = Arrays.asList("mike", "suzy"); @GetMapping("/api/people") - @Timed(quantiles = 0.95) + @Timed(percentiles = true) public List allPeople() { return people; } diff --git a/micrometer-spring-legacy/src/samples/resources/application.yml b/micrometer-spring-legacy/src/samples/resources/application.yml index 7f94e9ea34..771ba510e4 100644 --- a/micrometer-spring-legacy/src/samples/resources/application.yml +++ b/micrometer-spring-legacy/src/samples/resources/application.yml @@ -27,4 +27,7 @@ metrics: graphite.enabled: false influx.enabled: false jmx.enabled: false - prometheus.enabled: false \ No newline at end of file + prometheus.enabled: false + +# % of the time, blow up on the Roulette endpoint +roulette.frequency: 0.8 \ No newline at end of file diff --git a/micrometer-spring-legacy/src/test/java/io/micrometer/spring/MetricsConfigurationTest.java b/micrometer-spring-legacy/src/test/java/io/micrometer/spring/MetricsConfigurationTest.java index 9c7f55d6d2..e61574714d 100644 --- a/micrometer-spring-legacy/src/test/java/io/micrometer/spring/MetricsConfigurationTest.java +++ b/micrometer-spring-legacy/src/test/java/io/micrometer/spring/MetricsConfigurationTest.java @@ -21,6 +21,7 @@ import io.micrometer.core.instrument.binder.LogbackMetrics; import io.micrometer.core.instrument.binder.MeterBinder; import io.micrometer.core.instrument.simple.SimpleMeterRegistry; +import io.micrometer.core.instrument.stats.hist.Histogram; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; @@ -119,7 +120,6 @@ public RestTemplate restTemplate() { @RestController static class PersonController { - @Timed @GetMapping("/api/people") Set personName() { return Collections.singleton("Jon"); diff --git a/micrometer-spring-legacy/src/test/java/io/micrometer/spring/scheduling/MetricsSchedulingAspectTest.java b/micrometer-spring-legacy/src/test/java/io/micrometer/spring/scheduling/ScheduledMethodMetricsTest.java similarity index 99% rename from micrometer-spring-legacy/src/test/java/io/micrometer/spring/scheduling/MetricsSchedulingAspectTest.java rename to micrometer-spring-legacy/src/test/java/io/micrometer/spring/scheduling/ScheduledMethodMetricsTest.java index f119497714..b37366f1db 100644 --- a/micrometer-spring-legacy/src/test/java/io/micrometer/spring/scheduling/MetricsSchedulingAspectTest.java +++ b/micrometer-spring-legacy/src/test/java/io/micrometer/spring/scheduling/ScheduledMethodMetricsTest.java @@ -38,7 +38,7 @@ @RunWith(SpringRunner.class) @SpringBootTest @TestPropertySource(properties = "metrics.useGlobalRegistry=false") -public class MetricsSchedulingAspectTest { +public class ScheduledMethodMetricsTest { static CountDownLatch longTaskStarted = new CountDownLatch(1); static CountDownLatch longTaskShouldComplete = new CountDownLatch(1); diff --git a/micrometer-spring-legacy/src/samples/.gitignore b/scripts/.gitignore similarity index 100% rename from micrometer-spring-legacy/src/samples/.gitignore rename to scripts/.gitignore diff --git a/micrometer-spring-legacy/src/samples/README.md b/scripts/README.md similarity index 100% rename from micrometer-spring-legacy/src/samples/README.md rename to scripts/README.md diff --git a/micrometer-spring-legacy/src/samples/atlas.sh b/scripts/atlas.sh similarity index 100% rename from micrometer-spring-legacy/src/samples/atlas.sh rename to scripts/atlas.sh diff --git a/micrometer-spring-legacy/src/samples/ganglia.sh b/scripts/ganglia.sh similarity index 100% rename from micrometer-spring-legacy/src/samples/ganglia.sh rename to scripts/ganglia.sh diff --git a/micrometer-spring-legacy/src/samples/graphite.sh b/scripts/graphite.sh similarity index 100% rename from micrometer-spring-legacy/src/samples/graphite.sh rename to scripts/graphite.sh diff --git a/micrometer-spring-legacy/src/samples/influx.sh b/scripts/influx.sh similarity index 100% rename from micrometer-spring-legacy/src/samples/influx.sh rename to scripts/influx.sh diff --git a/micrometer-spring-legacy/src/samples/prometheus.sh b/scripts/prometheus.sh similarity index 100% rename from micrometer-spring-legacy/src/samples/prometheus.sh rename to scripts/prometheus.sh diff --git a/starter/micrometer-atlas-starter/src/main/java/io/micrometer/atlas/AtlasMeterRegistry.java b/starter/micrometer-atlas-starter/src/main/java/io/micrometer/atlas/AtlasMeterRegistry.java index a633fb9697..1293985052 100644 --- a/starter/micrometer-atlas-starter/src/main/java/io/micrometer/atlas/AtlasMeterRegistry.java +++ b/starter/micrometer-atlas-starter/src/main/java/io/micrometer/atlas/AtlasMeterRegistry.java @@ -1,12 +1,12 @@ /** * Copyright 2017 Pivotal Software, Inc. - * + *

* 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 - * + *

+ * 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. @@ -15,11 +15,22 @@ */ package io.micrometer.atlas; +import com.netflix.spectator.api.histogram.PercentileBuckets; +import com.netflix.spectator.api.histogram.PercentileDistributionSummary; +import com.netflix.spectator.api.histogram.PercentileTimer; import com.netflix.spectator.atlas.AtlasConfig; import com.netflix.spectator.atlas.AtlasRegistry; -import io.micrometer.core.instrument.Clock; -import io.micrometer.core.instrument.NamingConvention; +import io.micrometer.core.instrument.*; +import io.micrometer.core.instrument.spectator.SpectatorDistributionSummary; +import io.micrometer.core.instrument.spectator.SpectatorTimer; import io.micrometer.core.instrument.spectator.step.StepSpectatorMeterRegistry; +import io.micrometer.core.instrument.stats.hist.Bucket; +import io.micrometer.core.instrument.stats.hist.Histogram; +import io.micrometer.core.instrument.stats.quantile.Quantiles; + +import java.awt.*; +import java.util.concurrent.TimeUnit; +import java.util.function.UnaryOperator; /** * @author Jon Schneider @@ -62,4 +73,42 @@ public void stop() { private AtlasRegistry getAtlasRegistry() { return (AtlasRegistry) this.getSpectatorRegistry(); } + + // Precomputed values for the corresponding buckets. This is done to avoid expensive + // String.format calls when creating new instances of a percentile variant. The + // String.format calls uses regex internally to parse out the `%` substitutions which + // has a lot of overhead. + private static final String[] TAG_VALUES; + + static { + int length = PercentileBuckets.length(); + TAG_VALUES = new String[length]; + for (int i = 0; i < length; ++i) { + TAG_VALUES[i] = String.format("T%04X", i); + } + } + + @Override + protected Timer newTimer(Meter.Id id, String description, Histogram.Builder histogram, Quantiles quantiles) { + if (histogram != null && histogram.create(TimeUnit.NANOSECONDS, Histogram.Type.Normal).isPercentiles()) { + // scale nanosecond precise quantile values to seconds + registerQuantilesGaugeIfNecessary(id, quantiles, t -> t / 1.0e6); + com.netflix.spectator.api.Timer timer = PercentileTimer.get(getSpectatorRegistry(), getSpectatorRegistry().createId(id.getConventionName(), toSpectatorTags(id.getConventionTags()))); + return new SpectatorTimer(id, description, timer, clock, quantiles, null); + } + + return super.newTimer(id, description, histogram, quantiles); + } + + @Override + protected DistributionSummary newDistributionSummary(Meter.Id id, String description, Histogram.Builder histogram, Quantiles quantiles) { + if(histogram != null && histogram.create(TimeUnit.NANOSECONDS, Histogram.Type.Normal).isPercentiles()) { + registerQuantilesGaugeIfNecessary(id, quantiles, UnaryOperator.identity()); + com.netflix.spectator.api.DistributionSummary ds = PercentileDistributionSummary.get(getSpectatorRegistry(), getSpectatorRegistry().createId(id.getConventionName(), + toSpectatorTags(id.getConventionTags()))); + return new SpectatorDistributionSummary(id, description, ds, quantiles, null); + } + + return super.newDistributionSummary(id, description, histogram, quantiles); + } }