Commit 65e68760 authored by Jon Schneider's avatar Jon Schneider Committed by Phillip Webb

Upgrade to Micrometer 1.0.0-rc.3

Upgrade to Micrometer 1.0.0-rc.3 and refactor existing
auto-configuration to align with updated APIs.

Note that Spring MVC instrumentation has now changed from an interceptor
to a Filter.

See gh-10906
parent fa191d8c
...@@ -19,6 +19,7 @@ package org.springframework.boot.actuate.autoconfigure.metrics; ...@@ -19,6 +19,7 @@ package org.springframework.boot.actuate.autoconfigure.metrics;
import io.micrometer.core.instrument.binder.MeterBinder; import io.micrometer.core.instrument.binder.MeterBinder;
import io.micrometer.core.instrument.binder.jvm.JvmMemoryMetrics; import io.micrometer.core.instrument.binder.jvm.JvmMemoryMetrics;
import io.micrometer.core.instrument.binder.logging.LogbackMetrics; import io.micrometer.core.instrument.binder.logging.LogbackMetrics;
import io.micrometer.core.instrument.binder.system.ProcessorMetrics;
import io.micrometer.core.instrument.binder.system.UptimeMetrics; import io.micrometer.core.instrument.binder.system.UptimeMetrics;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
...@@ -53,4 +54,9 @@ class MeterBindersConfiguration { ...@@ -53,4 +54,9 @@ class MeterBindersConfiguration {
return new UptimeMetrics(); return new UptimeMetrics();
} }
@Bean
@ConditionalOnMissingBean(ProcessorMetrics.class)
public ProcessorMetrics processorMetrics() {
return new ProcessorMetrics();
}
} }
...@@ -67,7 +67,7 @@ public abstract class StepRegistryProperties { ...@@ -67,7 +67,7 @@ public abstract class StepRegistryProperties {
this.step = step; this.step = step;
} }
public Boolean getEnabled() { public Boolean isEnabled() {
return this.enabled; return this.enabled;
} }
......
...@@ -18,7 +18,7 @@ package org.springframework.boot.actuate.autoconfigure.metrics.export; ...@@ -18,7 +18,7 @@ package org.springframework.boot.actuate.autoconfigure.metrics.export;
import java.time.Duration; import java.time.Duration;
import io.micrometer.core.instrument.spectator.step.StepRegistryConfig; import io.micrometer.core.instrument.step.StepRegistryConfig;
/** /**
* Base class for {@link StepRegistryProperties} to {@link StepRegistryConfig} adapters. * Base class for {@link StepRegistryProperties} to {@link StepRegistryConfig} adapters.
...@@ -53,7 +53,7 @@ public abstract class StepRegistryPropertiesConfigAdapter<T extends StepRegistry ...@@ -53,7 +53,7 @@ public abstract class StepRegistryPropertiesConfigAdapter<T extends StepRegistry
@Override @Override
public boolean enabled() { public boolean enabled() {
return get(T::getEnabled, C::enabled); return get(T::isEnabled, C::enabled);
} }
@Override @Override
......
...@@ -21,14 +21,12 @@ import io.micrometer.atlas.AtlasMeterRegistry; ...@@ -21,14 +21,12 @@ import io.micrometer.atlas.AtlasMeterRegistry;
import io.micrometer.core.instrument.Clock; import io.micrometer.core.instrument.Clock;
import org.springframework.boot.actuate.autoconfigure.metrics.export.MetricsExporter; import org.springframework.boot.actuate.autoconfigure.metrics.export.MetricsExporter;
import org.springframework.boot.actuate.autoconfigure.metrics.export.StringToDurationConverter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
/** /**
* Configuration for exporting metrics to Atlas. * Configuration for exporting metrics to Atlas.
...@@ -39,7 +37,6 @@ import org.springframework.context.annotation.Import; ...@@ -39,7 +37,6 @@ import org.springframework.context.annotation.Import;
*/ */
@Configuration @Configuration
@ConditionalOnClass(AtlasMeterRegistry.class) @ConditionalOnClass(AtlasMeterRegistry.class)
@Import(StringToDurationConverter.class)
@EnableConfigurationProperties(AtlasProperties.class) @EnableConfigurationProperties(AtlasProperties.class)
public class AtlasExportConfiguration { public class AtlasExportConfiguration {
......
...@@ -49,7 +49,7 @@ class AtlasPropertiesConfigAdapter extends ...@@ -49,7 +49,7 @@ class AtlasPropertiesConfigAdapter extends
@Override @Override
public boolean enabled() { public boolean enabled() {
return get(AtlasProperties::getEnabled, AtlasConfig::enabled); return get(AtlasProperties::isEnabled, AtlasConfig::enabled);
} }
@Override @Override
......
...@@ -21,14 +21,12 @@ import io.micrometer.datadog.DatadogConfig; ...@@ -21,14 +21,12 @@ import io.micrometer.datadog.DatadogConfig;
import io.micrometer.datadog.DatadogMeterRegistry; import io.micrometer.datadog.DatadogMeterRegistry;
import org.springframework.boot.actuate.autoconfigure.metrics.export.MetricsExporter; import org.springframework.boot.actuate.autoconfigure.metrics.export.MetricsExporter;
import org.springframework.boot.actuate.autoconfigure.metrics.export.StringToDurationConverter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
/** /**
* Configuration for exporting metrics to Datadog. * Configuration for exporting metrics to Datadog.
...@@ -39,7 +37,6 @@ import org.springframework.context.annotation.Import; ...@@ -39,7 +37,6 @@ import org.springframework.context.annotation.Import;
@Configuration @Configuration
@ConditionalOnClass(DatadogMeterRegistry.class) @ConditionalOnClass(DatadogMeterRegistry.class)
@ConditionalOnProperty("spring.metrics.datadog.api-key") @ConditionalOnProperty("spring.metrics.datadog.api-key")
@Import(StringToDurationConverter.class)
@EnableConfigurationProperties(DatadogProperties.class) @EnableConfigurationProperties(DatadogProperties.class)
public class DatadogExportConfiguration { public class DatadogExportConfiguration {
......
...@@ -16,8 +16,6 @@ ...@@ -16,8 +16,6 @@
package org.springframework.boot.actuate.autoconfigure.metrics.export.datadog; package org.springframework.boot.actuate.autoconfigure.metrics.export.datadog;
import java.time.Duration;
import org.springframework.boot.actuate.autoconfigure.metrics.export.StepRegistryProperties; import org.springframework.boot.actuate.autoconfigure.metrics.export.StepRegistryProperties;
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationProperties;
...@@ -43,18 +41,10 @@ public class DatadogProperties extends StepRegistryProperties { ...@@ -43,18 +41,10 @@ public class DatadogProperties extends StepRegistryProperties {
private String hostTag; private String hostTag;
/** /**
* The bucket filter clamping the bucket domain of timer percentiles histograms to * The URI to ship metrics to. If you need to publish metrics to an internal proxy en route to
* some max value. This is used to limit the number of buckets shipped to Prometheus * datadoghq, you can define the location of the proxy with this.
* to save on storage.
*/
private Duration timerPercentilesMax = Duration.ofMinutes(2);
/**
* The bucket filter clamping the bucket domain of timer percentiles histograms to
* some min value. This is used to limit the number of buckets shipped to Prometheus
* to save on storage.
*/ */
private Duration timerPercentilesMin = Duration.ofMillis(10); private String uri;
public String getApiKey() { public String getApiKey() {
return this.apiKey; return this.apiKey;
...@@ -72,19 +62,11 @@ public class DatadogProperties extends StepRegistryProperties { ...@@ -72,19 +62,11 @@ public class DatadogProperties extends StepRegistryProperties {
this.hostTag = hostKey; this.hostTag = hostKey;
} }
public Duration getTimerPercentilesMax() { public String getUri() {
return this.timerPercentilesMax; return this.uri;
}
public void setTimerPercentilesMax(Duration timerPercentilesMax) {
this.timerPercentilesMax = timerPercentilesMax;
}
public Duration getTimerPercentilesMin() {
return this.timerPercentilesMin;
} }
public void setTimerPercentilesMin(Duration timerPercentilesMin) { public void setUri(String uri) {
this.timerPercentilesMin = timerPercentilesMin; this.uri = uri;
} }
} }
...@@ -16,8 +16,6 @@ ...@@ -16,8 +16,6 @@
package org.springframework.boot.actuate.autoconfigure.metrics.export.datadog; package org.springframework.boot.actuate.autoconfigure.metrics.export.datadog;
import java.time.Duration;
import io.micrometer.datadog.DatadogConfig; import io.micrometer.datadog.DatadogConfig;
import org.springframework.boot.actuate.autoconfigure.metrics.export.StepRegistryPropertiesConfigAdapter; import org.springframework.boot.actuate.autoconfigure.metrics.export.StepRegistryPropertiesConfigAdapter;
...@@ -49,15 +47,7 @@ class DatadogPropertiesConfigAdapter ...@@ -49,15 +47,7 @@ class DatadogPropertiesConfigAdapter
} }
@Override @Override
public Duration timerPercentilesMax() { public String uri() {
return get(DatadogProperties::getTimerPercentilesMax, return get(DatadogProperties::getUri, DatadogConfig::uri);
DatadogConfig::timerPercentilesMax);
} }
@Override
public Duration timerPercentilesMin() {
return get(DatadogProperties::getTimerPercentilesMin,
DatadogConfig::timerPercentilesMin);
}
} }
...@@ -22,14 +22,12 @@ import io.micrometer.ganglia.GangliaConfig; ...@@ -22,14 +22,12 @@ import io.micrometer.ganglia.GangliaConfig;
import io.micrometer.ganglia.GangliaMeterRegistry; import io.micrometer.ganglia.GangliaMeterRegistry;
import org.springframework.boot.actuate.autoconfigure.metrics.export.MetricsExporter; import org.springframework.boot.actuate.autoconfigure.metrics.export.MetricsExporter;
import org.springframework.boot.actuate.autoconfigure.metrics.export.StringToDurationConverter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
/** /**
* Configuration for exporting metrics to Ganglia. * Configuration for exporting metrics to Ganglia.
...@@ -39,7 +37,6 @@ import org.springframework.context.annotation.Import; ...@@ -39,7 +37,6 @@ import org.springframework.context.annotation.Import;
*/ */
@Configuration @Configuration
@ConditionalOnClass(GangliaMeterRegistry.class) @ConditionalOnClass(GangliaMeterRegistry.class)
@Import(StringToDurationConverter.class)
@EnableConfigurationProperties(GangliaProperties.class) @EnableConfigurationProperties(GangliaProperties.class)
public class GangliaExportConfiguration { public class GangliaExportConfiguration {
......
...@@ -77,7 +77,7 @@ public class GangliaProperties { ...@@ -77,7 +77,7 @@ public class GangliaProperties {
*/ */
private Integer port; private Integer port;
public Boolean getEnabled() { public Boolean isEnabled() {
return this.enabled; return this.enabled;
} }
......
...@@ -47,7 +47,7 @@ class GangliaPropertiesConfigAdapter ...@@ -47,7 +47,7 @@ class GangliaPropertiesConfigAdapter
@Override @Override
public boolean enabled() { public boolean enabled() {
return get(GangliaProperties::getEnabled, GangliaConfig::enabled); return get(GangliaProperties::isEnabled, GangliaConfig::enabled);
} }
@Override @Override
......
...@@ -22,14 +22,12 @@ import io.micrometer.graphite.GraphiteConfig; ...@@ -22,14 +22,12 @@ import io.micrometer.graphite.GraphiteConfig;
import io.micrometer.graphite.GraphiteMeterRegistry; import io.micrometer.graphite.GraphiteMeterRegistry;
import org.springframework.boot.actuate.autoconfigure.metrics.export.MetricsExporter; import org.springframework.boot.actuate.autoconfigure.metrics.export.MetricsExporter;
import org.springframework.boot.actuate.autoconfigure.metrics.export.StringToDurationConverter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
/** /**
* Configuration for exporting metrics to Graphite. * Configuration for exporting metrics to Graphite.
...@@ -39,7 +37,6 @@ import org.springframework.context.annotation.Import; ...@@ -39,7 +37,6 @@ import org.springframework.context.annotation.Import;
*/ */
@Configuration @Configuration
@ConditionalOnClass(GraphiteMeterRegistry.class) @ConditionalOnClass(GraphiteMeterRegistry.class)
@Import(StringToDurationConverter.class)
@EnableConfigurationProperties(GraphiteProperties.class) @EnableConfigurationProperties(GraphiteProperties.class)
public class GraphiteExportConfiguration { public class GraphiteExportConfiguration {
......
...@@ -67,7 +67,7 @@ public class GraphiteProperties { ...@@ -67,7 +67,7 @@ public class GraphiteProperties {
*/ */
private GraphiteProtocol protocol = GraphiteProtocol.Pickled; private GraphiteProtocol protocol = GraphiteProtocol.Pickled;
public Boolean getEnabled() { public Boolean isEnabled() {
return this.enabled; return this.enabled;
} }
......
...@@ -47,7 +47,7 @@ class GraphitePropertiesConfigAdapter ...@@ -47,7 +47,7 @@ class GraphitePropertiesConfigAdapter
@Override @Override
public boolean enabled() { public boolean enabled() {
return get(GraphiteProperties::getEnabled, GraphiteConfig::enabled); return get(GraphiteProperties::isEnabled, GraphiteConfig::enabled);
} }
@Override @Override
......
...@@ -21,14 +21,12 @@ import io.micrometer.influx.InfluxConfig; ...@@ -21,14 +21,12 @@ import io.micrometer.influx.InfluxConfig;
import io.micrometer.influx.InfluxMeterRegistry; import io.micrometer.influx.InfluxMeterRegistry;
import org.springframework.boot.actuate.autoconfigure.metrics.export.MetricsExporter; import org.springframework.boot.actuate.autoconfigure.metrics.export.MetricsExporter;
import org.springframework.boot.actuate.autoconfigure.metrics.export.StringToDurationConverter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
/** /**
* Configuration for exporting metrics to Influx. * Configuration for exporting metrics to Influx.
...@@ -38,7 +36,6 @@ import org.springframework.context.annotation.Import; ...@@ -38,7 +36,6 @@ import org.springframework.context.annotation.Import;
*/ */
@Configuration @Configuration
@ConditionalOnClass(InfluxMeterRegistry.class) @ConditionalOnClass(InfluxMeterRegistry.class)
@Import(StringToDurationConverter.class)
@EnableConfigurationProperties(InfluxProperties.class) @EnableConfigurationProperties(InfluxProperties.class)
public class InfluxExportConfiguration { public class InfluxExportConfiguration {
......
...@@ -16,8 +16,6 @@ ...@@ -16,8 +16,6 @@
package org.springframework.boot.actuate.autoconfigure.metrics.export.influx; package org.springframework.boot.actuate.autoconfigure.metrics.export.influx;
import java.time.Duration;
import io.micrometer.influx.InfluxConsistency; import io.micrometer.influx.InfluxConsistency;
import org.springframework.boot.actuate.autoconfigure.metrics.export.StepRegistryProperties; import org.springframework.boot.actuate.autoconfigure.metrics.export.StepRegistryProperties;
...@@ -68,20 +66,6 @@ public class InfluxProperties extends StepRegistryProperties { ...@@ -68,20 +66,6 @@ public class InfluxProperties extends StepRegistryProperties {
*/ */
private Boolean compressed; private Boolean compressed;
/**
* The bucket filter clamping the bucket domain of timer percentiles histograms to
* some max value. This is used to limit the number of buckets shipped to Prometheus
* to save on storage.
*/
private Duration timerPercentilesMax = Duration.ofMinutes(2);
/**
* The bucket filter clamping the bucket domain of timer percentiles histograms to
* some min value. This is used to limit the number of buckets shipped to Prometheus
* to save on storage.
*/
private Duration timerPercentilesMin = Duration.ofMillis(10);
public String getDb() { public String getDb() {
return this.db; return this.db;
} }
...@@ -137,20 +121,4 @@ public class InfluxProperties extends StepRegistryProperties { ...@@ -137,20 +121,4 @@ public class InfluxProperties extends StepRegistryProperties {
public void setCompressed(Boolean compressed) { public void setCompressed(Boolean compressed) {
this.compressed = compressed; this.compressed = compressed;
} }
public Duration getTimerPercentilesMax() {
return this.timerPercentilesMax;
}
public void setTimerPercentilesMax(Duration timerPercentilesMax) {
this.timerPercentilesMax = timerPercentilesMax;
}
public Duration getTimerPercentilesMin() {
return this.timerPercentilesMin;
}
public void setTimerPercentilesMin(Duration timerPercentilesMin) {
this.timerPercentilesMin = timerPercentilesMin;
}
} }
...@@ -73,17 +73,4 @@ class InfluxPropertiesConfigAdapter ...@@ -73,17 +73,4 @@ class InfluxPropertiesConfigAdapter
public boolean compressed() { public boolean compressed() {
return get(InfluxProperties::getCompressed, InfluxConfig::compressed); return get(InfluxProperties::getCompressed, InfluxConfig::compressed);
} }
@Override
public Duration timerPercentilesMax() {
return get(InfluxProperties::getTimerPercentilesMax,
InfluxConfig::timerPercentilesMax);
}
@Override
public Duration timerPercentilesMin() {
return get(InfluxProperties::getTimerPercentilesMin,
InfluxConfig::timerPercentilesMin);
}
} }
...@@ -41,20 +41,11 @@ public class PrometheusProperties { ...@@ -41,20 +41,11 @@ public class PrometheusProperties {
private Boolean descriptions = true; private Boolean descriptions = true;
/** /**
* The bucket filter clamping the bucket domain of timer percentiles histograms to * The step size (reporting frequency) to use.
* some max value. This is used to limit the number of buckets shipped to Prometheus
* to save on storage.
*/ */
private Duration timerPercentilesMax = Duration.ofMinutes(2); private Duration step = Duration.ofMinutes(1);
/** public Boolean isEnabled() {
* The bucket filter clamping the bucket domain of timer percentiles histograms to
* some min value. This is used to limit the number of buckets shipped to Prometheus
* to save on storage.
*/
private Duration timerPercentilesMin = Duration.ofMillis(10);
public Boolean getEnabled() {
return this.enabled; return this.enabled;
} }
...@@ -70,20 +61,11 @@ public class PrometheusProperties { ...@@ -70,20 +61,11 @@ public class PrometheusProperties {
this.descriptions = descriptions; this.descriptions = descriptions;
} }
public Duration getTimerPercentilesMax() { public Duration getStep() {
return this.timerPercentilesMax; return this.step;
}
public void setTimerPercentilesMax(Duration timerPercentilesMax) {
this.timerPercentilesMax = timerPercentilesMax;
}
public Duration getTimerPercentilesMin() {
return this.timerPercentilesMin;
} }
public void setTimerPercentilesMin(Duration timerPercentilesMin) { public void setStep(Duration step) {
this.timerPercentilesMin = timerPercentilesMin; this.step = step;
} }
} }
...@@ -49,15 +49,7 @@ class PrometheusPropertiesConfigAdapter ...@@ -49,15 +49,7 @@ class PrometheusPropertiesConfigAdapter
} }
@Override @Override
public Duration timerPercentilesMin() { public Duration step() {
return get(PrometheusProperties::getTimerPercentilesMin, return get(PrometheusProperties::getStep, PrometheusConfig::step);
PrometheusConfig::timerPercentilesMin);
} }
@Override
public Duration timerPercentilesMax() {
return get(PrometheusProperties::getTimerPercentilesMax,
PrometheusConfig::timerPercentilesMax);
}
} }
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
package org.springframework.boot.actuate.autoconfigure.metrics.export.simple; package org.springframework.boot.actuate.autoconfigure.metrics.export.simple;
import io.micrometer.core.instrument.Clock; import io.micrometer.core.instrument.Clock;
import io.micrometer.core.instrument.simple.SimpleConfig;
import io.micrometer.core.instrument.simple.SimpleMeterRegistry; import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
import org.springframework.boot.actuate.autoconfigure.metrics.export.MetricsExporter; import org.springframework.boot.actuate.autoconfigure.metrics.export.MetricsExporter;
...@@ -39,8 +40,8 @@ public class SimpleExportConfiguration { ...@@ -39,8 +40,8 @@ public class SimpleExportConfiguration {
@Bean @Bean
@ConditionalOnProperty(value = "spring.metrics.export.simple.enabled", matchIfMissing = true) @ConditionalOnProperty(value = "spring.metrics.export.simple.enabled", matchIfMissing = true)
@ConditionalOnMissingBean(MetricsExporter.class) @ConditionalOnMissingBean(MetricsExporter.class)
public MetricsExporter simpleExporter(Clock clock) { public MetricsExporter simpleExporter(SimpleConfig config, Clock clock) {
return () -> new SimpleMeterRegistry(clock); return () -> new SimpleMeterRegistry(config, clock);
} }
@Bean @Bean
...@@ -49,4 +50,9 @@ public class SimpleExportConfiguration { ...@@ -49,4 +50,9 @@ public class SimpleExportConfiguration {
return Clock.SYSTEM; return Clock.SYSTEM;
} }
@Bean
@ConditionalOnMissingBean(SimpleConfig.class)
public SimpleConfig simpleConfig(SimpleProperties simpleProperties) {
return new SimplePropertiesConfigAdapter(simpleProperties);
}
} }
...@@ -16,10 +16,12 @@ ...@@ -16,10 +16,12 @@
package org.springframework.boot.actuate.autoconfigure.metrics.export.simple; package org.springframework.boot.actuate.autoconfigure.metrics.export.simple;
import io.micrometer.core.instrument.simple.SimpleMeterRegistry; import java.time.Duration;
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationProperties;
import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
/** /**
* {@link ConfigurationProperties} for configuring metrics export to a * {@link ConfigurationProperties} for configuring metrics export to a
* {@link SimpleMeterRegistry}. * {@link SimpleMeterRegistry}.
...@@ -30,8 +32,16 @@ import org.springframework.boot.context.properties.ConfigurationProperties; ...@@ -30,8 +32,16 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties(prefix = "spring.metrics.export.simple") @ConfigurationProperties(prefix = "spring.metrics.export.simple")
public class SimpleProperties { public class SimpleProperties {
/**
* Enable publishing to the backend.
*/
private boolean enabled = true; private boolean enabled = true;
/**
* The step size (reporting frequency) to use.
*/
private Duration step = Duration.ofSeconds(10);
public boolean isEnabled() { public boolean isEnabled() {
return this.enabled; return this.enabled;
} }
...@@ -40,4 +50,11 @@ public class SimpleProperties { ...@@ -40,4 +50,11 @@ public class SimpleProperties {
this.enabled = enabled; this.enabled = enabled;
} }
public Duration getStep() {
return this.step;
}
public void setStep(Duration step) {
this.step = step;
}
} }
...@@ -14,26 +14,41 @@ ...@@ -14,26 +14,41 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.boot.actuate.autoconfigure.metrics.export; package org.springframework.boot.actuate.autoconfigure.metrics.export.simple;
import java.time.Duration; import java.time.Duration;
import org.springframework.boot.context.properties.ConfigurationPropertiesBinding; import io.micrometer.core.instrument.simple.SimpleConfig;
import org.springframework.core.convert.converter.Converter;
import org.springframework.boot.actuate.autoconfigure.metrics.export.PropertiesConfigAdapter;
/** /**
* A {@link Converter} to create a {@link Duration} from a {@link String}. * Adapter to convert {@link SimpleProperties} to a {@link SimpleConfig}.
* *
* @author Jon Schneider * @author Jon Schneider
* @author Andy Wilkinson
* @since 2.0.0 * @since 2.0.0
*/ */
@ConfigurationPropertiesBinding public class SimplePropertiesConfigAdapter extends
public class StringToDurationConverter implements Converter<String, Duration> { PropertiesConfigAdapter<SimpleProperties, SimpleConfig> implements SimpleConfig {
private static final SimpleConfig DEFAULTS = (key) -> null;
public SimplePropertiesConfigAdapter(SimpleProperties properties) {
super(properties, DEFAULTS);
}
@Override @Override
public Duration convert(String source) { public String get(String k) {
return Duration.parse(source); return null;
} }
@Override
public boolean enabled() {
return get(SimpleProperties::isEnabled, SimpleConfig::enabled);
}
@Override
public Duration step() {
return get(SimpleProperties::getStep, SimpleConfig::step);
}
} }
...@@ -17,18 +17,17 @@ ...@@ -17,18 +17,17 @@
package org.springframework.boot.actuate.autoconfigure.metrics.export.statsd; package org.springframework.boot.actuate.autoconfigure.metrics.export.statsd;
import io.micrometer.core.instrument.Clock; import io.micrometer.core.instrument.Clock;
import io.micrometer.core.instrument.util.HierarchicalNameMapper;
import io.micrometer.statsd.StatsdConfig; import io.micrometer.statsd.StatsdConfig;
import io.micrometer.statsd.StatsdMeterRegistry; import io.micrometer.statsd.StatsdMeterRegistry;
import org.springframework.boot.actuate.autoconfigure.metrics.export.MetricsExporter; import org.springframework.boot.actuate.autoconfigure.metrics.export.MetricsExporter;
import org.springframework.boot.actuate.autoconfigure.metrics.export.StringToDurationConverter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
/** /**
* Configuration for exporting metrics to StatsD. * Configuration for exporting metrics to StatsD.
...@@ -38,7 +37,6 @@ import org.springframework.context.annotation.Import; ...@@ -38,7 +37,6 @@ import org.springframework.context.annotation.Import;
*/ */
@Configuration @Configuration
@ConditionalOnClass(StatsdMeterRegistry.class) @ConditionalOnClass(StatsdMeterRegistry.class)
@Import(StringToDurationConverter.class)
@EnableConfigurationProperties(StatsdProperties.class) @EnableConfigurationProperties(StatsdProperties.class)
public class StatsdExportConfiguration { public class StatsdExportConfiguration {
...@@ -50,8 +48,8 @@ public class StatsdExportConfiguration { ...@@ -50,8 +48,8 @@ public class StatsdExportConfiguration {
@Bean @Bean
@ConditionalOnProperty(value = "spring.metrics.export.statsd.enabled", matchIfMissing = true) @ConditionalOnProperty(value = "spring.metrics.export.statsd.enabled", matchIfMissing = true)
public MetricsExporter statsdExporter(StatsdConfig statsdConfig, Clock clock) { public MetricsExporter statsdExporter(StatsdConfig statsdConfig, HierarchicalNameMapper hierarchicalNameMapper, Clock clock) {
return () -> new StatsdMeterRegistry(statsdConfig, clock); return () -> new StatsdMeterRegistry(statsdConfig, hierarchicalNameMapper, clock);
} }
@Bean @Bean
...@@ -60,4 +58,9 @@ public class StatsdExportConfiguration { ...@@ -60,4 +58,9 @@ public class StatsdExportConfiguration {
return Clock.SYSTEM; return Clock.SYSTEM;
} }
@Bean
@ConditionalOnMissingBean
public HierarchicalNameMapper hierarchicalNameMapper() {
return HierarchicalNameMapper.DEFAULT;
}
} }
...@@ -68,37 +68,7 @@ public class StatsdProperties { ...@@ -68,37 +68,7 @@ public class StatsdProperties {
*/ */
private Integer queueSize = Integer.MAX_VALUE; private Integer queueSize = Integer.MAX_VALUE;
/** public Boolean isEnabled() {
* Used to create a bucket filter clamping the bucket domain of timer percentiles
* histograms to some max value. This is used to limit the number of buckets shipped
* to StatsD to save on storage.
*/
private Duration timerPercentilesMax = Duration.ofMinutes(2);
/**
* Used to create a bucket filter clamping the bucket domain of timer percentiles
* histograms to some min value. This is used to limit the number of buckets shipped
* to StatsD to save on storage.
*/
private Duration timerPercentilesMin = Duration.ofMillis(10);
public Duration getTimerPercentilesMax() {
return this.timerPercentilesMax;
}
public void setTimerPercentilesMax(Duration timerPercentilesMax) {
this.timerPercentilesMax = timerPercentilesMax;
}
public Duration getTimerPercentilesMin() {
return this.timerPercentilesMin;
}
public void setTimerPercentilesMin(Duration timerPercentilesMin) {
this.timerPercentilesMin = timerPercentilesMin;
}
public Boolean getEnabled() {
return this.enabled; return this.enabled;
} }
......
...@@ -50,7 +50,7 @@ public class StatsdPropertiesConfigAdapter extends ...@@ -50,7 +50,7 @@ public class StatsdPropertiesConfigAdapter extends
@Override @Override
public boolean enabled() { public boolean enabled() {
return get(StatsdProperties::getEnabled, StatsdConfig::enabled); return get(StatsdProperties::isEnabled, StatsdConfig::enabled);
} }
@Override @Override
......
...@@ -20,7 +20,7 @@ import io.micrometer.core.instrument.MeterRegistry; ...@@ -20,7 +20,7 @@ import io.micrometer.core.instrument.MeterRegistry;
import org.springframework.boot.actuate.autoconfigure.metrics.MetricsProperties; import org.springframework.boot.actuate.autoconfigure.metrics.MetricsProperties;
import org.springframework.boot.actuate.metrics.web.servlet.DefaultWebMvcTagsProvider; import org.springframework.boot.actuate.metrics.web.servlet.DefaultWebMvcTagsProvider;
import org.springframework.boot.actuate.metrics.web.servlet.MetricsHandlerInterceptor; import org.springframework.boot.actuate.metrics.web.servlet.MetricsFilter;
import org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetrics; import org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetrics;
import org.springframework.boot.actuate.metrics.web.servlet.WebMvcTagsProvider; import org.springframework.boot.actuate.metrics.web.servlet.WebMvcTagsProvider;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
...@@ -30,8 +30,7 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties ...@@ -30,8 +30,7 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.DispatcherServlet; import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.handler.HandlerMappingIntrospector;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/** /**
* Configures instrumentation of Spring Web MVC servlet-based request mappings. * Configures instrumentation of Spring Web MVC servlet-based request mappings.
...@@ -61,27 +60,7 @@ public class WebMvcMetricsConfiguration { ...@@ -61,27 +60,7 @@ public class WebMvcMetricsConfiguration {
} }
@Bean @Bean
public MetricsHandlerInterceptor webMetricsInterceptor( public MetricsFilter webMetricsFilter(WebMvcMetrics controllerMetrics, HandlerMappingIntrospector introspector) {
WebMvcMetrics controllerMetrics) { return new MetricsFilter(controllerMetrics, introspector);
return new MetricsHandlerInterceptor(controllerMetrics);
} }
@Configuration
public class MetricsServletRequestInterceptorConfiguration
implements WebMvcConfigurer {
private final MetricsHandlerInterceptor handlerInterceptor;
public MetricsServletRequestInterceptorConfiguration(
MetricsHandlerInterceptor handlerInterceptor) {
this.handlerInterceptor = handlerInterceptor;
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(this.handlerInterceptor);
}
}
} }
...@@ -14,39 +14,37 @@ ...@@ -14,39 +14,37 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.boot.actuate.metrics.web.servlet; package org.springframework.boot.actuate.metrics;
import javax.servlet.http.HttpServletRequest; import java.lang.reflect.AnnotatedElement;
import javax.servlet.http.HttpServletResponse; import java.util.Arrays;
import java.util.stream.Stream;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; import io.micrometer.core.annotation.Timed;
import io.micrometer.core.annotation.TimedSet;
import org.springframework.core.annotation.AnnotationUtils;
/** /**
* Intercepts incoming HTTP requests and records metrics about execution time and results. * A utility class for finding {@link Timed} annotations.
* *
* @author Jon Schneider * @author Jon Schneider
* @since 2.0.0 * @since 2.0.0
*/ */
public class MetricsHandlerInterceptor extends HandlerInterceptorAdapter { public final class TimedUtils {
private TimedUtils() {
private final WebMvcMetrics webMvcMetrics;
public MetricsHandlerInterceptor(WebMvcMetrics webMvcMetrics) {
this.webMvcMetrics = webMvcMetrics;
} }
@Override public static Stream<Timed> findTimedAnnotations(AnnotatedElement element) {
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Timed t = AnnotationUtils.findAnnotation(element, Timed.class);
Object handler) throws Exception { if (t != null)
this.webMvcMetrics.preHandle(request, handler); return Stream.of(t);
return super.preHandle(request, response, handler);
}
@Override TimedSet ts = AnnotationUtils.findAnnotation(element, TimedSet.class);
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, if (ts != null) {
Object handler, Exception ex) throws Exception { return Arrays.stream(ts.value());
this.webMvcMetrics.record(request, response, ex); }
super.afterCompletion(request, response, handler, ex);
}
return Stream.empty();
}
} }
...@@ -23,7 +23,6 @@ import java.util.concurrent.TimeUnit; ...@@ -23,7 +23,6 @@ import java.util.concurrent.TimeUnit;
import io.micrometer.core.instrument.MeterRegistry; import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Timer; import io.micrometer.core.instrument.Timer;
import io.micrometer.core.instrument.stats.hist.Histogram;
import org.springframework.core.NamedThreadLocal; import org.springframework.core.NamedThreadLocal;
import org.springframework.http.HttpRequest; import org.springframework.http.HttpRequest;
...@@ -98,13 +97,10 @@ class MetricsClientHttpRequestInterceptor implements ClientHttpRequestIntercepto ...@@ -98,13 +97,10 @@ class MetricsClientHttpRequestInterceptor implements ClientHttpRequestIntercepto
private Timer.Builder getTimeBuilder(HttpRequest request, private Timer.Builder getTimeBuilder(HttpRequest request,
ClientHttpResponse response) { ClientHttpResponse response) {
Timer.Builder builder = Timer.builder(this.metricName) return Timer.builder(this.metricName)
.tags(this.tagProvider.getTags(urlTemplate.get(), request, response)) .tags(this.tagProvider.getTags(urlTemplate.get(), request, response))
.description("Timer of RestTemplate operation"); .description("Timer of RestTemplate operation")
if (this.recordPercentiles) { .publishPercentileHistogram(this.recordPercentiles);
builder = builder.histogram(Histogram.percentilesTime());
}
return builder;
} }
} }
/*
* Copyright 2012-2017 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.web.servlet;
import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.web.filter.OncePerRequestFilter;
import org.springframework.web.servlet.HandlerExecutionChain;
import org.springframework.web.servlet.handler.HandlerMappingIntrospector;
import org.springframework.web.servlet.handler.MatchableHandlerMapping;
import org.springframework.web.util.NestedServletException;
/**
* Intercepts incoming HTTP requests and records metrics about execution time and results.
*
* @author Jon Schneider
* @since 2.0.0
*/
@Order(Ordered.HIGHEST_PRECEDENCE)
public class MetricsFilter extends OncePerRequestFilter {
private final WebMvcMetrics webMvcMetrics;
private final HandlerMappingIntrospector mappingIntrospector;
private final Logger logger = LoggerFactory.getLogger(MetricsFilter.class);
public MetricsFilter(WebMvcMetrics webMvcMetrics,
HandlerMappingIntrospector mappingIntrospector) {
this.webMvcMetrics = webMvcMetrics;
this.mappingIntrospector = mappingIntrospector;
}
@Override
protected boolean shouldNotFilterAsyncDispatch() {
return false;
}
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
HandlerExecutionChain handler;
try {
MatchableHandlerMapping matchableHandlerMapping = this.mappingIntrospector
.getMatchableHandlerMapping(request);
handler = matchableHandlerMapping.getHandler(request);
}
catch (Exception e) {
this.logger.debug("Unable to time request", e);
return;
}
if (handler != null) {
Object handlerObject = handler.getHandler();
this.webMvcMetrics.preHandle(request, handlerObject);
try {
filterChain.doFilter(request, response);
// when an async operation is complete, the whole filter gets called
// again with isAsyncStarted = false
if (!request.isAsyncStarted()) {
this.webMvcMetrics.record(request, response, null);
}
}
catch (NestedServletException e) {
this.webMvcMetrics.record(request, response, e.getCause());
throw e;
}
}
else {
filterChain.doFilter(request, response);
}
}
}
...@@ -17,7 +17,6 @@ ...@@ -17,7 +17,6 @@
package org.springframework.boot.actuate.metrics.web.servlet; package org.springframework.boot.actuate.metrics.web.servlet;
import java.lang.reflect.AnnotatedElement; import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Method;
import java.util.Collections; import java.util.Collections;
import java.util.IdentityHashMap; import java.util.IdentityHashMap;
import java.util.Map; import java.util.Map;
...@@ -25,28 +24,21 @@ import java.util.Set; ...@@ -25,28 +24,21 @@ import java.util.Set;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.function.Supplier; import java.util.function.Supplier;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import io.micrometer.core.annotation.Timed;
import io.micrometer.core.instrument.LongTaskTimer;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Tag;
import io.micrometer.core.instrument.Tags;
import io.micrometer.core.instrument.Timer;
import io.micrometer.core.instrument.stats.hist.Histogram;
import io.micrometer.core.instrument.stats.quantile.WindowSketchQuantiles;
import io.micrometer.core.instrument.util.AnnotationUtils;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.springframework.boot.actuate.metrics.TimedUtils;
import org.springframework.util.ObjectUtils; import org.springframework.util.ObjectUtils;
import org.springframework.web.context.request.RequestAttributes; import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.method.HandlerMethod; import org.springframework.web.method.HandlerMethod;
import io.micrometer.core.annotation.Timed;
import io.micrometer.core.instrument.*;
/** /**
* Support class for Spring MVC metrics. * Support class for Spring MVC metrics.
* *
...@@ -154,25 +146,21 @@ public class WebMvcMetrics { ...@@ -154,25 +146,21 @@ public class WebMvcMetrics {
HttpServletResponse response, Throwable thrown, TimerConfig config) { HttpServletResponse response, Throwable thrown, TimerConfig config) {
Timer.Builder builder = Timer.builder(config.getName()) Timer.Builder builder = Timer.builder(config.getName())
.tags(this.tagsProvider.httpRequestTags(request, response, thrown)) .tags(this.tagsProvider.httpRequestTags(request, response, thrown))
.tags(config.getExtraTags()).description("Timer of servlet request"); .tags(config.getExtraTags()).description("Timer of servlet request")
if (config.getQuantiles().length > 0) { .publishPercentileHistogram(config.histogram);
WindowSketchQuantiles quantiles = WindowSketchQuantiles if (config.getPercentiles().length > 0) {
.quantiles(config.getQuantiles()).create(); builder = builder.publishPercentiles(config.getPercentiles());
builder = builder.quantiles(quantiles);
}
if (config.isPercentiles()) {
builder = builder.histogram(Histogram.percentilesTime());
} }
return builder; return builder;
} }
private LongTaskTimer longTaskTimer(TimerConfig config, HttpServletRequest request, private LongTaskTimer longTaskTimer(TimerConfig config, HttpServletRequest request,
Object handler) { Object handler) {
Iterable<Tag> tags = Tags.concat( return LongTaskTimer.builder(config.getName())
this.tagsProvider.httpLongRequestTags(request, handler), .tags(this.tagsProvider.httpLongRequestTags(request, handler))
config.getExtraTags()); .tags(config.getExtraTags())
return this.registry.more().longTaskTimer(this.registry.createId(config.getName(), .description("Timer of long servlet request")
tags, "Timer of long servlet request")); .register(this.registry);
} }
private Set<TimerConfig> longTaskTimed(Object handler) { private Set<TimerConfig> longTaskTimed(Object handler) {
...@@ -210,22 +198,15 @@ public class WebMvcMetrics { ...@@ -210,22 +198,15 @@ public class WebMvcMetrics {
} }
private Set<TimerConfig> getNonLongTaskAnnotationConfig(AnnotatedElement element) { private Set<TimerConfig> getNonLongTaskAnnotationConfig(AnnotatedElement element) {
return findTimedAnnotations(element).filter((t) -> !t.longTask()) return TimedUtils.findTimedAnnotations(element).filter((t) -> !t.longTask())
.map(this::fromAnnotation).collect(Collectors.toSet()); .map(this::fromAnnotation).collect(Collectors.toSet());
} }
private Set<TimerConfig> getLongTaskAnnotationConfig(AnnotatedElement element) { private Set<TimerConfig> getLongTaskAnnotationConfig(AnnotatedElement element) {
return findTimedAnnotations(element).filter(Timed::longTask) return TimedUtils.findTimedAnnotations(element).filter(Timed::longTask)
.map(this::fromAnnotation).collect(Collectors.toSet()); .map(this::fromAnnotation).collect(Collectors.toSet());
} }
private Stream<Timed> findTimedAnnotations(AnnotatedElement element) {
if (element instanceof Class<?>) {
return AnnotationUtils.findTimed((Class<?>) element);
}
return AnnotationUtils.findTimed((Method) element);
}
private TimerConfig fromAnnotation(Timed timed) { private TimerConfig fromAnnotation(Timed timed) {
return new TimerConfig(timed, this::getServerRequestName); return new TimerConfig(timed, this::getServerRequestName);
} }
...@@ -240,22 +221,22 @@ public class WebMvcMetrics { ...@@ -240,22 +221,22 @@ public class WebMvcMetrics {
private final Iterable<Tag> extraTags; private final Iterable<Tag> extraTags;
private final double[] quantiles; private final double[] percentiles;
private final boolean percentiles; private final boolean histogram;
TimerConfig(String name, boolean percentiles) { TimerConfig(String name, boolean histogram) {
this.name = name; this.name = name;
this.extraTags = Collections.emptyList(); this.extraTags = Collections.emptyList();
this.quantiles = new double[0]; this.percentiles = new double[0];
this.percentiles = percentiles; this.histogram = histogram;
} }
TimerConfig(Timed timed, Supplier<String> name) { TimerConfig(Timed timed, Supplier<String> name) {
this.name = buildName(timed, name); this.name = buildName(timed, name);
this.extraTags = Tags.zip(timed.extraTags()); this.extraTags = Tags.zip(timed.extraTags());
this.quantiles = timed.quantiles();
this.percentiles = timed.percentiles(); this.percentiles = timed.percentiles();
this.histogram = timed.histogram();
} }
private String buildName(Timed timed, Supplier<String> name) { private String buildName(Timed timed, Supplier<String> name) {
...@@ -271,16 +252,16 @@ public class WebMvcMetrics { ...@@ -271,16 +252,16 @@ public class WebMvcMetrics {
return this.name; return this.name;
} }
public Iterable<Tag> getExtraTags() { Iterable<Tag> getExtraTags() {
return this.extraTags; return this.extraTags;
} }
public double[] getQuantiles() { double[] getPercentiles() {
return this.quantiles; return this.percentiles;
} }
public boolean isPercentiles() { boolean isHistogram() {
return this.percentiles; return this.histogram;
} }
@Override @Override
...@@ -301,5 +282,4 @@ public class WebMvcMetrics { ...@@ -301,5 +282,4 @@ public class WebMvcMetrics {
} }
} }
} }
...@@ -21,11 +21,14 @@ import java.util.Optional; ...@@ -21,11 +21,14 @@ import java.util.Optional;
import java.util.stream.Stream; import java.util.stream.Stream;
import io.micrometer.core.instrument.MeterRegistry; import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.MockClock;
import io.micrometer.core.instrument.Statistic; import io.micrometer.core.instrument.Statistic;
import io.micrometer.core.instrument.composite.CompositeMeterRegistry; import io.micrometer.core.instrument.composite.CompositeMeterRegistry;
import io.micrometer.core.instrument.simple.SimpleConfig;
import io.micrometer.core.instrument.simple.SimpleMeterRegistry; import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
import org.junit.Test; import org.junit.Test;
import static io.micrometer.core.instrument.MockClock.clock;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
/** /**
...@@ -36,7 +39,7 @@ import static org.assertj.core.api.Assertions.assertThat; ...@@ -36,7 +39,7 @@ import static org.assertj.core.api.Assertions.assertThat;
*/ */
public class MetricsEndpointTests { public class MetricsEndpointTests {
private final MeterRegistry registry = new SimpleMeterRegistry(); private final MeterRegistry registry = new SimpleMeterRegistry(SimpleConfig.DEFAULT, new MockClock());
private final MetricsEndpoint endpoint = new MetricsEndpoint(this.registry); private final MetricsEndpoint endpoint = new MetricsEndpoint(this.registry);
...@@ -74,6 +77,8 @@ public class MetricsEndpointTests { ...@@ -74,6 +77,8 @@ public class MetricsEndpointTests {
this.registry.counter("cache", "result", "hit", "host", "1").increment(2); this.registry.counter("cache", "result", "hit", "host", "1").increment(2);
this.registry.counter("cache", "result", "miss", "host", "1").increment(2); this.registry.counter("cache", "result", "miss", "host", "1").increment(2);
this.registry.counter("cache", "result", "hit", "host", "2").increment(2); this.registry.counter("cache", "result", "hit", "host", "2").increment(2);
clock(registry).add(SimpleConfig.DEFAULT_STEP);
MetricsEndpoint.MetricResponse response = this.endpoint.metric("cache", MetricsEndpoint.MetricResponse response = this.endpoint.metric("cache",
Collections.emptyList()); Collections.emptyList());
assertThat(response.getName()).isEqualTo("cache"); assertThat(response.getName()).isEqualTo("cache");
...@@ -87,6 +92,8 @@ public class MetricsEndpointTests { ...@@ -87,6 +92,8 @@ public class MetricsEndpointTests {
@Test @Test
public void metricWithSpaceInTagValue() { public void metricWithSpaceInTagValue() {
this.registry.counter("counter", "key", "a space").increment(2); this.registry.counter("counter", "key", "a space").increment(2);
clock(registry).add(SimpleConfig.DEFAULT_STEP);
MetricsEndpoint.MetricResponse response = this.endpoint.metric("counter", MetricsEndpoint.MetricResponse response = this.endpoint.metric("counter",
Collections.singletonList("key:a space")); Collections.singletonList("key:a space"));
assertThat(response.getName()).isEqualTo("counter"); assertThat(response.getName()).isEqualTo("counter");
......
...@@ -22,16 +22,20 @@ import java.util.Map; ...@@ -22,16 +22,20 @@ import java.util.Map;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import io.micrometer.core.instrument.MeterRegistry; import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.MockClock;
import io.micrometer.core.instrument.binder.jvm.JvmMemoryMetrics; import io.micrometer.core.instrument.binder.jvm.JvmMemoryMetrics;
import io.micrometer.core.instrument.simple.SimpleConfig;
import io.micrometer.core.instrument.simple.SimpleMeterRegistry; import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.endpoint.web.test.WebEndpointRunners; import org.springframework.boot.actuate.endpoint.web.test.WebEndpointRunners;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.test.web.reactive.server.WebTestClient; import org.springframework.test.web.reactive.server.WebTestClient;
import static io.micrometer.core.instrument.MockClock.clock;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
/** /**
...@@ -42,7 +46,7 @@ import static org.assertj.core.api.Assertions.assertThat; ...@@ -42,7 +46,7 @@ import static org.assertj.core.api.Assertions.assertThat;
*/ */
@RunWith(WebEndpointRunners.class) @RunWith(WebEndpointRunners.class)
public class MetricsEndpointWebIntegrationTests { public class MetricsEndpointWebIntegrationTests {
private static MeterRegistry registry = new SimpleMeterRegistry(SimpleConfig.DEFAULT, new MockClock());
private static WebTestClient client; private static WebTestClient client;
private final ObjectMapper mapper = new ObjectMapper(); private final ObjectMapper mapper = new ObjectMapper();
...@@ -50,7 +54,7 @@ public class MetricsEndpointWebIntegrationTests { ...@@ -50,7 +54,7 @@ public class MetricsEndpointWebIntegrationTests {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Test @Test
public void listNames() throws IOException { public void listNames() throws IOException {
String responseBody = MetricsEndpointWebIntegrationTests.client.get() String responseBody = client.get()
.uri("/application/metrics").exchange().expectStatus().isOk() .uri("/application/metrics").exchange().expectStatus().isOk()
.expectBody(String.class).returnResult().getResponseBody(); .expectBody(String.class).returnResult().getResponseBody();
Map<String, List<String>> names = this.mapper.readValue(responseBody, Map.class); Map<String, List<String>> names = this.mapper.readValue(responseBody, Map.class);
...@@ -59,14 +63,16 @@ public class MetricsEndpointWebIntegrationTests { ...@@ -59,14 +63,16 @@ public class MetricsEndpointWebIntegrationTests {
@Test @Test
public void selectByName() throws IOException { public void selectByName() throws IOException {
MetricsEndpointWebIntegrationTests.client.get() clock(registry).add(SimpleConfig.DEFAULT_STEP);
client.get()
.uri("/application/metrics/jvm.memory.used").exchange().expectStatus() .uri("/application/metrics/jvm.memory.used").exchange().expectStatus()
.isOk().expectBody().jsonPath("$.name").isEqualTo("jvm.memory.used"); .isOk().expectBody().jsonPath("$.name").isEqualTo("jvm.memory.used");
} }
@Test @Test
public void selectByTag() { public void selectByTag() {
MetricsEndpointWebIntegrationTests.client.get() clock(registry).add(SimpleConfig.DEFAULT_STEP);
client.get()
.uri("/application/metrics/jvm.memory.used?tag=id:Compressed%20Class%20Space") .uri("/application/metrics/jvm.memory.used?tag=id:Compressed%20Class%20Space")
.exchange().expectStatus().isOk().expectBody().jsonPath("$.name") .exchange().expectStatus().isOk().expectBody().jsonPath("$.name")
.isEqualTo("jvm.memory.used"); .isEqualTo("jvm.memory.used");
...@@ -77,7 +83,7 @@ public class MetricsEndpointWebIntegrationTests { ...@@ -77,7 +83,7 @@ public class MetricsEndpointWebIntegrationTests {
@Bean @Bean
public MeterRegistry registry() { public MeterRegistry registry() {
return new SimpleMeterRegistry(); return registry;
} }
@Bean @Bean
......
...@@ -19,8 +19,10 @@ package org.springframework.boot.actuate.metrics.web.client; ...@@ -19,8 +19,10 @@ package org.springframework.boot.actuate.metrics.web.client;
import java.util.stream.StreamSupport; import java.util.stream.StreamSupport;
import io.micrometer.core.instrument.MeterRegistry; import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.MockClock;
import io.micrometer.core.instrument.Statistic; import io.micrometer.core.instrument.Statistic;
import io.micrometer.core.instrument.Tag; import io.micrometer.core.instrument.Tag;
import io.micrometer.core.instrument.simple.SimpleConfig;
import io.micrometer.core.instrument.simple.SimpleMeterRegistry; import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
import org.junit.Test; import org.junit.Test;
...@@ -31,6 +33,8 @@ import org.springframework.test.web.client.match.MockRestRequestMatchers; ...@@ -31,6 +33,8 @@ import org.springframework.test.web.client.match.MockRestRequestMatchers;
import org.springframework.test.web.client.response.MockRestResponseCreators; import org.springframework.test.web.client.response.MockRestResponseCreators;
import org.springframework.web.client.RestTemplate; import org.springframework.web.client.RestTemplate;
import static io.micrometer.core.instrument.MockClock.clock;
import static java.util.stream.StreamSupport.stream;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
/** /**
...@@ -42,7 +46,7 @@ public class MetricsRestTemplateCustomizerTests { ...@@ -42,7 +46,7 @@ public class MetricsRestTemplateCustomizerTests {
@Test @Test
public void interceptRestTemplate() { public void interceptRestTemplate() {
MeterRegistry registry = new SimpleMeterRegistry(); MeterRegistry registry = new SimpleMeterRegistry(SimpleConfig.DEFAULT, new MockClock());
RestTemplate restTemplate = new RestTemplate(); RestTemplate restTemplate = new RestTemplate();
MetricsRestTemplateCustomizer customizer = new MetricsRestTemplateCustomizer( MetricsRestTemplateCustomizer customizer = new MetricsRestTemplateCustomizer(
registry, new DefaultRestTemplateExchangeTagsProvider(), registry, new DefaultRestTemplateExchangeTagsProvider(),
...@@ -55,13 +59,12 @@ public class MetricsRestTemplateCustomizerTests { ...@@ -55,13 +59,12 @@ public class MetricsRestTemplateCustomizerTests {
.andRespond(MockRestResponseCreators.withSuccess("OK", .andRespond(MockRestResponseCreators.withSuccess("OK",
MediaType.APPLICATION_JSON)); MediaType.APPLICATION_JSON));
String result = restTemplate.getForObject("/test/{id}", String.class, 123); String result = restTemplate.getForObject("/test/{id}", String.class, 123);
clock(registry).add(SimpleConfig.DEFAULT_STEP);
assertThat(registry.find("http.client.requests").meters())
.anySatisfy(m -> assertThat(stream(m.getId().getTags().spliterator(), false).map(Tag::getKey)).doesNotContain("bucket"));
assertThat(registry.find("http.client.requests") assertThat(registry.find("http.client.requests")
.tags("method", "GET", "uri", "/test/{id}", "status", "200") .tags("method", "GET", "uri", "/test/{id}", "status", "200")
.value(Statistic.Count, 1.0).timer()).isPresent(); .value(Statistic.Count, 1.0).timer()).isPresent();
assertThat(registry.find("http.client.requests").meters()
.stream().flatMap((m) -> StreamSupport
.stream(m.getId().getTags().spliterator(), false))
.map(Tag::getKey)).contains("bucket");
assertThat(result).isEqualTo("OK"); assertThat(result).isEqualTo("OK");
mockServer.verify(); mockServer.verify();
} }
......
...@@ -16,12 +16,14 @@ ...@@ -16,12 +16,14 @@
package org.springframework.boot.actuate.metrics.web.servlet; package org.springframework.boot.actuate.metrics.web.servlet;
import io.micrometer.core.instrument.Clock;
import io.micrometer.core.instrument.MeterRegistry; import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.MockClock;
import io.micrometer.core.instrument.simple.SimpleConfig;
import io.micrometer.core.instrument.simple.SimpleMeterRegistry; import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
...@@ -36,87 +38,81 @@ import org.springframework.web.bind.annotation.RequestMapping; ...@@ -36,87 +38,81 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.WebApplicationContext; import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.handler.HandlerMappingIntrospector;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
/** /**
* Tests for {@link MetricsHandlerInterceptor} with auto-timed server requests.
*
* @author Jon Schneider * @author Jon Schneider
*/ */
@RunWith(SpringRunner.class) @RunWith(SpringRunner.class)
@WebAppConfiguration @WebAppConfiguration
public class MetricsHandlerInterceptorAutoTimedTests { public class MetricsFilterAutoTimedTests {
@Autowired @Autowired
private MeterRegistry registry; private MeterRegistry registry;
@Autowired @Autowired
private WebApplicationContext context; private MockClock clock;
private MockMvc mvc; @Autowired
private WebApplicationContext context;
@Before private MockMvc mvc;
public void setupMockMvc() {
this.mvc = MockMvcBuilders.webAppContextSetup(this.context).build();
}
@Test @Autowired
public void metricsCanBeAutoTimed() throws Exception { private MetricsFilter filter;
this.mvc.perform(get("/api/10")).andExpect(status().isOk());
assertThat(
this.registry.find("http.server.requests").tags("status", "200").timer())
.hasValueSatisfying((t) -> assertThat(t.count()).isEqualTo(1));
}
@Configuration @Before
@EnableWebMvc public void setupMockMvc() {
@Import(Controller.class) this.mvc = MockMvcBuilders.webAppContextSetup(this.context)
static class TestConfiguration { .addFilters(filter)
.build();
@Bean }
MeterRegistry meterRegistry() {
return new SimpleMeterRegistry();
}
@Bean
WebMvcMetrics webMvcMetrics(MeterRegistry meterRegistry) {
return new WebMvcMetrics(meterRegistry, new DefaultWebMvcTagsProvider(),
"http.server.requests", true, true);
}
@Configuration @Test
static class HandlerInterceptorConfiguration implements WebMvcConfigurer { public void metricsCanBeAutoTimed() throws Exception {
this.mvc.perform(get("/api/10")).andExpect(status().isOk());
private final WebMvcMetrics webMvcMetrics; clock.add(SimpleConfig.DEFAULT_STEP);
assertThat(this.registry.find("http.server.requests").tags("status", "200").timer())
.hasValueSatisfying((t) -> assertThat(t.count()).isEqualTo(1));
}
HandlerInterceptorConfiguration(WebMvcMetrics webMvcMetrics) { @Configuration
this.webMvcMetrics = webMvcMetrics; @EnableWebMvc
} @Import({Controller.class})
static class TestConfiguration {
@Bean
MockClock clock() {
return new MockClock();
}
@Override @Bean
public void addInterceptors(InterceptorRegistry registry) { MeterRegistry meterRegistry(Clock clock) {
registry.addInterceptor( return new SimpleMeterRegistry(SimpleConfig.DEFAULT, clock);
new MetricsHandlerInterceptor(this.webMvcMetrics)); }
}
@Bean
public WebMvcMetrics controllerMetrics(MeterRegistry registry) {
return new WebMvcMetrics(registry, new DefaultWebMvcTagsProvider(), "http.server.requests", true,
false);
} }
} @Bean
public MetricsFilter webMetricsFilter(WebMvcMetrics controllerMetrics, HandlerMappingIntrospector introspector) {
@RestController return new MetricsFilter(controllerMetrics, introspector);
@RequestMapping("/api")
static class Controller {
@GetMapping("/{id}")
public String successful(@PathVariable Long id) {
return id.toString();
} }
}
}
@RestController
@RequestMapping("/api")
static class Controller {
@GetMapping("/{id}")
public String successful(@PathVariable Long id) {
return id.toString();
}
}
} }
...@@ -17,8 +17,11 @@ ...@@ -17,8 +17,11 @@
package org.springframework.boot.actuate.metrics.web.servlet; package org.springframework.boot.actuate.metrics.web.servlet;
import io.micrometer.core.annotation.Timed; import io.micrometer.core.annotation.Timed;
import io.micrometer.core.instrument.Clock;
import io.micrometer.core.instrument.MeterRegistry; import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.MockClock;
import io.micrometer.core.instrument.Statistic; import io.micrometer.core.instrument.Statistic;
import io.micrometer.core.instrument.simple.SimpleConfig;
import io.micrometer.core.instrument.simple.SimpleMeterRegistry; import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
...@@ -33,15 +36,10 @@ import org.springframework.test.context.junit4.SpringRunner; ...@@ -33,15 +36,10 @@ import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.context.web.WebAppConfiguration; import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.WebApplicationContext; import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.handler.HandlerMappingIntrospector;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatCode; import static org.assertj.core.api.Assertions.assertThatCode;
...@@ -63,42 +61,64 @@ public class WebMvcMetricsIntegrationTests { ...@@ -63,42 +61,64 @@ public class WebMvcMetricsIntegrationTests {
@Autowired @Autowired
private SimpleMeterRegistry registry; private SimpleMeterRegistry registry;
@Autowired
private MockClock clock;
private MockMvc mvc; private MockMvc mvc;
@Autowired
private MetricsFilter filter;
@Before @Before
public void setupMockMvc() { public void setupMockMvc() {
this.mvc = MockMvcBuilders.webAppContextSetup(this.context).build(); this.mvc = MockMvcBuilders.webAppContextSetup(this.context)
.addFilters(filter)
.build();
} }
@Test @Test
public void handledExceptionIsRecordedInMetricTag() throws Exception { public void handledExceptionIsRecordedInMetricTag() throws Exception {
this.mvc.perform(get("/api/handledError")).andExpect(status().is5xxServerError()); this.mvc.perform(get("/api/handledError")).andExpect(status().is5xxServerError());
clock.add(SimpleConfig.DEFAULT_STEP);
assertThat(this.registry.find("http.server.requests") assertThat(this.registry.find("http.server.requests")
.tags("exception", "Exception1").value(Statistic.Count, 1.0).timer()) .tags("exception", "Exception1").value(Statistic.Count, 1.0).timer())
.isPresent(); .isPresent();
} }
@Test @Test
public void rethrownExceptionIsRecordedInMetricTag() throws Exception { public void rethrownExceptionIsRecordedInMetricTag() throws Exception {
assertThatCode(() -> this.mvc.perform(get("/api/rethrownError")) assertThatCode(() -> this.mvc.perform(get("/api/rethrownError"))
.andExpect(status().is5xxServerError())); .andExpect(status().is5xxServerError()));
clock.add(SimpleConfig.DEFAULT_STEP);
assertThat(this.registry.find("http.server.requests") assertThat(this.registry.find("http.server.requests")
.tags("exception", "Exception2").value(Statistic.Count, 1.0).timer()) .tags("exception", "Exception2").value(Statistic.Count, 1.0).timer())
.isPresent(); .isPresent();
} }
@Configuration @Configuration
@EnableWebMvc
static class TestConfiguration { static class TestConfiguration {
@Bean
MockClock clock() {
return new MockClock();
}
@Bean
MeterRegistry meterRegistry(Clock clock) {
return new SimpleMeterRegistry(SimpleConfig.DEFAULT, clock);
}
@Bean @Bean
WebMvcMetrics webMvcMetrics(MeterRegistry meterRegistry) { public WebMvcMetrics controllerMetrics(MeterRegistry registry) {
return new WebMvcMetrics(meterRegistry, new DefaultWebMvcTagsProvider(), return new WebMvcMetrics(registry, new DefaultWebMvcTagsProvider(), "http.server.requests", true,
"http.server.requests", true, true); false);
} }
@Bean @Bean
MeterRegistry registry() { public MetricsFilter webMetricsFilter(WebMvcMetrics controllerMetrics, HandlerMappingIntrospector introspector) {
return new SimpleMeterRegistry(); return new MetricsFilter(controllerMetrics, introspector);
} }
@RestController @RestController
...@@ -122,33 +142,12 @@ public class WebMvcMetricsIntegrationTests { ...@@ -122,33 +142,12 @@ public class WebMvcMetricsIntegrationTests {
} }
} }
@Configuration
@EnableWebMvc
static class HandlerInterceptorConfiguration implements WebMvcConfigurer {
private final WebMvcMetrics webMvcMetrics;
HandlerInterceptorConfiguration(WebMvcMetrics webMvcMetrics) {
this.webMvcMetrics = webMvcMetrics;
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(
new MetricsHandlerInterceptor(this.webMvcMetrics));
}
}
} }
static class Exception1 extends RuntimeException { static class Exception1 extends RuntimeException {
} }
static class Exception2 extends RuntimeException { static class Exception2 extends RuntimeException {
} }
@ControllerAdvice @ControllerAdvice
...@@ -168,7 +167,5 @@ public class WebMvcMetricsIntegrationTests { ...@@ -168,7 +167,5 @@ public class WebMvcMetricsIntegrationTests {
ResponseEntity<String> rethrowError(Exception2 ex) throws Throwable { ResponseEntity<String> rethrowError(Exception2 ex) throws Throwable {
throw ex; throw ex;
} }
} }
}
} \ No newline at end of file
...@@ -114,7 +114,7 @@ ...@@ -114,7 +114,7 @@
<logback.version>1.2.3</logback.version> <logback.version>1.2.3</logback.version>
<lombok.version>1.16.18</lombok.version> <lombok.version>1.16.18</lombok.version>
<mariadb.version>2.1.2</mariadb.version> <mariadb.version>2.1.2</mariadb.version>
<micrometer.version>1.0.0-rc.2</micrometer.version> <micrometer.version>1.0.0-SNAPSHOT</micrometer.version>
<mssql-jdbc.version>6.2.2.jre8</mssql-jdbc.version> <mssql-jdbc.version>6.2.2.jre8</mssql-jdbc.version>
<mockito.version>2.11.0</mockito.version> <mockito.version>2.11.0</mockito.version>
<mongo-driver-reactivestreams.version>1.6.0</mongo-driver-reactivestreams.version> <mongo-driver-reactivestreams.version>1.6.0</mongo-driver-reactivestreams.version>
......
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