diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/pom.xml b/spring-boot-project/spring-boot-actuator-autoconfigure/pom.xml
index 9e458ae80b5..d7dd3b602d7 100644
--- a/spring-boot-project/spring-boot-actuator-autoconfigure/pom.xml
+++ b/spring-boot-project/spring-boot-actuator-autoconfigure/pom.xml
@@ -137,6 +137,11 @@
micrometer-registry-statsd
true
+
+ io.micrometer
+ micrometer-registry-wavefront
+ true
+
io.projectreactor.ipc
reactor-netty
diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/wavefront/WavefrontMetricsExportAutoConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/wavefront/WavefrontMetricsExportAutoConfiguration.java
new file mode 100644
index 00000000000..e10cedd6251
--- /dev/null
+++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/wavefront/WavefrontMetricsExportAutoConfiguration.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2012-2018 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.autoconfigure.metrics.export.wavefront;
+
+import io.micrometer.core.instrument.Clock;
+import io.micrometer.wavefront.WavefrontConfig;
+import io.micrometer.wavefront.WavefrontMeterRegistry;
+
+import org.springframework.boot.actuate.autoconfigure.metrics.MetricsAutoConfiguration;
+import org.springframework.boot.actuate.autoconfigure.metrics.export.simple.SimpleMetricsExportAutoConfiguration;
+import org.springframework.boot.autoconfigure.AutoConfigureAfter;
+import org.springframework.boot.autoconfigure.AutoConfigureBefore;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * {@link EnableAutoConfiguration Auto-configuration} for exporting metrics to Wavefront.
+ *
+ * @author Jon Schneider
+ * @since 2.0.0
+ */
+@Configuration
+@AutoConfigureBefore(SimpleMetricsExportAutoConfiguration.class)
+@AutoConfigureAfter(MetricsAutoConfiguration.class)
+@ConditionalOnBean(Clock.class)
+@ConditionalOnClass(WavefrontMeterRegistry.class)
+@ConditionalOnProperty(prefix = "management.metrics.export.wavefront", name = "enabled", havingValue = "true", matchIfMissing = true)
+@EnableConfigurationProperties(WavefrontProperties.class)
+public class WavefrontMetricsExportAutoConfiguration {
+
+ @Bean
+ @ConditionalOnMissingBean(WavefrontConfig.class)
+ public WavefrontConfig wavefrontConfig(WavefrontProperties props) {
+ return new WavefrontPropertiesConfigAdapter(props);
+ }
+
+ @Bean(destroyMethod = "stop")
+ @ConditionalOnMissingBean
+ public WavefrontMeterRegistry wavefrontMeterRegistry(WavefrontConfig config,
+ Clock clock) {
+ return new WavefrontMeterRegistry(config, clock);
+ }
+
+}
diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/wavefront/WavefrontProperties.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/wavefront/WavefrontProperties.java
new file mode 100644
index 00000000000..bb9fa170ae9
--- /dev/null
+++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/wavefront/WavefrontProperties.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2012-2018 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.autoconfigure.metrics.export.wavefront;
+
+import java.net.URI;
+
+import org.springframework.boot.actuate.autoconfigure.metrics.export.properties.StepRegistryProperties;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+
+/**
+ * {@link ConfigurationProperties} for configuring Wavefront metrics export.
+ *
+ * @author Jon Schneider
+ * @since 2.0.0
+ */
+@ConfigurationProperties("management.metrics.export.wavefront")
+public class WavefrontProperties extends StepRegistryProperties {
+
+ /**
+ * URI to which metrics are published. May represent a Wavefront sidecar or the
+ * Wavefront API host. This host could also represent an internal proxy set up in your
+ * environment that forwards metrics data to the Wavefront API host.
+ *
+ * If publishing metrics to a Wavefront proxy (as described in
+ * https://docs.wavefront.com/proxies_installing.html), the host must be in the
+ * proxy://HOST:PORT format.
+ */
+ private URI uri;
+
+ /**
+ * Unique identifier for the app instance that is the source of metrics being
+ * published to Wavefront. Defaults to the local host name.
+ */
+ private String source;
+
+ /**
+ * API token used when publishing metrics directly to the Wavefront API host.
+ */
+ private String apiToken;
+
+ /**
+ * Global prefix to separate metrics originating from this app's white box
+ * instrumentation from those originating from other Wavefront integrations when
+ * viewed in the Wavefront UI.
+ */
+ private String globalPrefix;
+
+ public URI getUri() {
+ return this.uri;
+ }
+
+ public void setUri(URI uri) {
+ this.uri = uri;
+ }
+
+ public String getSource() {
+ return this.source;
+ }
+
+ public void setSource(String source) {
+ this.source = source;
+ }
+
+ public String getApiToken() {
+ return this.apiToken;
+ }
+
+ public void setApiToken(String apiToken) {
+ this.apiToken = apiToken;
+ }
+
+ public String getGlobalPrefix() {
+ return this.globalPrefix;
+ }
+
+ public void setGlobalPrefix(String globalPrefix) {
+ this.globalPrefix = globalPrefix;
+ }
+
+}
diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/wavefront/WavefrontPropertiesConfigAdapter.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/wavefront/WavefrontPropertiesConfigAdapter.java
new file mode 100644
index 00000000000..d2c6b1ca81d
--- /dev/null
+++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/wavefront/WavefrontPropertiesConfigAdapter.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2012-2018 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.autoconfigure.metrics.export.wavefront;
+
+import io.micrometer.wavefront.WavefrontConfig;
+
+import org.springframework.boot.actuate.autoconfigure.metrics.export.properties.PropertiesConfigAdapter;
+
+/**
+ * Adapter to convert {@link WavefrontProperties} to a {@link WavefrontConfig}.
+ *
+ * @author Jon Schneider
+ * @since 2.0.0
+ */
+public class WavefrontPropertiesConfigAdapter
+ extends PropertiesConfigAdapter implements WavefrontConfig {
+
+ public WavefrontPropertiesConfigAdapter(WavefrontProperties properties) {
+ super(properties);
+ }
+
+ @Override
+ public String get(String k) {
+ return null;
+ }
+
+ @Override
+ public String uri() {
+ return get(this::getUriAsString, WavefrontConfig.DEFAULT_DIRECT::uri);
+ }
+
+ @Override
+ public String source() {
+ return get(WavefrontProperties::getSource, WavefrontConfig.super::source);
+ }
+
+ @Override
+ public String apiToken() {
+ return get(WavefrontProperties::getApiToken, WavefrontConfig.super::apiToken);
+ }
+
+ @Override
+ public String globalPrefix() {
+ return get(WavefrontProperties::getGlobalPrefix,
+ WavefrontConfig.super::globalPrefix);
+ }
+
+ private String getUriAsString(WavefrontProperties properties) {
+ return properties.getUri() == null ? null : properties.getUri().toString();
+ }
+
+}
diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/wavefront/package-info.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/wavefront/package-info.java
new file mode 100644
index 00000000000..ca4ad6e6bc9
--- /dev/null
+++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/wavefront/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2012-2018 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.
+ */
+
+/**
+ * Support for exporting actuator metrics to Wavefront.
+ */
+package org.springframework.boot.actuate.autoconfigure.metrics.export.wavefront;
diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/resources/META-INF/spring.factories b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/resources/META-INF/spring.factories
index a93c06a0285..5d7f8b61137 100644
--- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/resources/META-INF/spring.factories
+++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/resources/META-INF/spring.factories
@@ -47,6 +47,7 @@ org.springframework.boot.actuate.autoconfigure.metrics.export.prometheus.Prometh
org.springframework.boot.actuate.autoconfigure.metrics.export.simple.SimpleMetricsExportAutoConfiguration,\
org.springframework.boot.actuate.autoconfigure.metrics.export.signalfx.SignalFxMetricsExportAutoConfiguration,\
org.springframework.boot.actuate.autoconfigure.metrics.export.statsd.StatsdMetricsExportAutoConfiguration,\
+org.springframework.boot.actuate.autoconfigure.metrics.export.wavefront.WavefrontMetricsExportAutoConfiguration,\
org.springframework.boot.actuate.autoconfigure.metrics.jdbc.DataSourcePoolMetricsAutoConfiguration,\
org.springframework.boot.actuate.autoconfigure.metrics.integration.MetricsIntegrationAutoConfiguration,\
org.springframework.boot.actuate.autoconfigure.metrics.web.client.RestTemplateMetricsAutoConfiguration,\
diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/export/wavefront/WavefrontMetricsExportAutoConfigurationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/export/wavefront/WavefrontMetricsExportAutoConfigurationTests.java
new file mode 100644
index 00000000000..c954701f55e
--- /dev/null
+++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/export/wavefront/WavefrontMetricsExportAutoConfigurationTests.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright 2012-2018 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.autoconfigure.metrics.export.wavefront;
+
+import java.util.Map;
+
+import io.micrometer.core.instrument.Clock;
+import io.micrometer.wavefront.WavefrontConfig;
+import io.micrometer.wavefront.WavefrontMeterRegistry;
+import org.junit.Test;
+
+import org.springframework.boot.autoconfigure.AutoConfigurations;
+import org.springframework.boot.test.context.assertj.AssertableApplicationContext;
+import org.springframework.boot.test.context.runner.ApplicationContextRunner;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Import;
+import org.springframework.test.util.ReflectionTestUtils;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
+/**
+ * Tests for {@link WavefrontMetricsExportAutoConfiguration}.
+ *
+ * @author Jon Schneider
+ */
+public class WavefrontMetricsExportAutoConfigurationTests {
+
+ private final ApplicationContextRunner runner = new ApplicationContextRunner()
+ .withConfiguration(
+ AutoConfigurations.of(WavefrontMetricsExportAutoConfiguration.class));
+
+ @Test
+ public void backsOffWithoutAClock() {
+ this.runner.run((context) -> assertThat(context)
+ .doesNotHaveBean(WavefrontMeterRegistry.class));
+ }
+
+ @Test
+ public void failsWithoutAnApiTokenWhenPublishingDirectly() {
+ this.runner.withUserConfiguration(BaseConfiguration.class)
+ .run((context) -> assertThat(context).hasFailed());
+ }
+
+ @Test
+ public void autoConfigurationCanBeDisabled() {
+ this.runner.withUserConfiguration(BaseConfiguration.class)
+ .withPropertyValues("management.metrics.export.wavefront.enabled=false")
+ .run((context) -> assertThat(context)
+ .doesNotHaveBean(WavefrontMeterRegistry.class)
+ .doesNotHaveBean(WavefrontConfig.class));
+ }
+
+ @Test
+ public void allowsConfigToBeCustomized() {
+ this.runner.withUserConfiguration(CustomConfigConfiguration.class)
+ .run((context) -> assertThat(context).hasSingleBean(Clock.class)
+ .hasSingleBean(WavefrontMeterRegistry.class)
+ .hasSingleBean(WavefrontConfig.class).hasBean("customConfig"));
+ }
+
+ @Test
+ public void allowsRegistryToBeCustomized() {
+ this.runner.withUserConfiguration(CustomRegistryConfiguration.class)
+ .withPropertyValues("management.metrics.export.wavefront.api-token=abcde")
+ .run((context) -> assertThat(context).hasSingleBean(Clock.class)
+ .hasSingleBean(WavefrontConfig.class)
+ .hasSingleBean(WavefrontMeterRegistry.class)
+ .hasBean("customRegistry"));
+ }
+
+ @Test
+ public void stopsMeterRegistryWhenContextIsClosed() {
+ this.runner.withUserConfiguration(BaseConfiguration.class)
+ .withPropertyValues("management.metrics.export.wavefront.api-token=abcde")
+ .run((context) -> {
+ WavefrontMeterRegistry registry = spyOnDisposableBean(
+ WavefrontMeterRegistry.class, context);
+ context.close();
+ verify(registry).stop();
+ });
+ }
+
+ @SuppressWarnings("unchecked")
+ private T spyOnDisposableBean(Class type,
+ AssertableApplicationContext context) {
+ String[] names = context.getBeanNamesForType(type);
+ assertThat(names).hasSize(1);
+ String registryBeanName = names[0];
+ Map disposableBeans = (Map) ReflectionTestUtils
+ .getField(context.getAutowireCapableBeanFactory(), "disposableBeans");
+ Object registryAdapter = disposableBeans.get(registryBeanName);
+ T registry = (T) spy(ReflectionTestUtils.getField(registryAdapter, "bean"));
+ ReflectionTestUtils.setField(registryAdapter, "bean", registry);
+ return registry;
+ }
+
+ @Configuration
+ static class BaseConfiguration {
+
+ @Bean
+ public Clock clock() {
+ return Clock.SYSTEM;
+ }
+
+ }
+
+ @Configuration
+ @Import(BaseConfiguration.class)
+ static class CustomConfigConfiguration {
+
+ @Bean
+ public WavefrontConfig customConfig() {
+ return new WavefrontConfig() {
+ @Override
+ public String get(String key) {
+ return null;
+ }
+
+ @Override
+ public String uri() {
+ return WavefrontConfig.DEFAULT_PROXY.uri();
+ }
+ };
+ }
+
+ }
+
+ @Configuration
+ @Import(BaseConfiguration.class)
+ static class CustomRegistryConfiguration {
+
+ @Bean(destroyMethod = "stop")
+ public WavefrontMeterRegistry customRegistry(WavefrontConfig config,
+ Clock clock) {
+ return new WavefrontMeterRegistry(config, clock);
+ }
+
+ }
+
+}
diff --git a/spring-boot-project/spring-boot-dependencies/pom.xml b/spring-boot-project/spring-boot-dependencies/pom.xml
index 4e5411b96b9..c07c4908aa8 100644
--- a/spring-boot-project/spring-boot-dependencies/pom.xml
+++ b/spring-boot-project/spring-boot-dependencies/pom.xml
@@ -902,6 +902,11 @@
micrometer-registry-statsd
${micrometer.version}
+
+ io.micrometer
+ micrometer-registry-wavefront
+ ${micrometer.version}
+
io.netty
netty-bom
diff --git a/spring-boot-project/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc b/spring-boot-project/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc
index 893faa39b20..051ee33b317 100644
--- a/spring-boot-project/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc
+++ b/spring-boot-project/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc
@@ -1391,6 +1391,11 @@ content into your application. Rather, pick only the properties that you need.
management.metrics.export.statsd.polling-frequency=10s # How often gauges will be polled. When a gauge is polled, its value is recalculated and if the value has changed, it is sent to the StatsD server.
management.metrics.export.statsd.port=8125 # Port of the StatsD server to receive exported metrics.
management.metrics.export.statsd.queue-size=2147483647 # Maximum size of the queue of items waiting to be sent to the StatsD server.
+ management.metrics.export.wavefront.api-token= # API token used when publishing metrics directly to the Wavefront API host.
+ management.metrics.export.wavefront.enabled= # Whether exporting of metrics to this backend is enabled.
+ management.metrics.export.wavefront.global-prefix= # Global prefix to separate metrics originating from this app's white box instrumentation from those originating from other Wavefront integrations when viewed in the Wavefront UI.
+ management.metrics.export.wavefront.source= # Unique identifier for the app instance that is the source of metrics being published to Wavefront. Defaults to the local host name.
+ management.metrics.export.wavefront.uri= # URI to which metrics are published. May represent a Wavefront sidecar or the Wavefront API host. This host could also represent an internal proxy set up in your environment that forwards metrics data to the Wavefront API host.
management.metrics.use-global-registry=true # Whether auto-configured MeterRegistry implementations should be bound to the global static registry on Metrics.
management.metrics.web.client.max-uri-tags=100 # Maximum number of unique URI tag values allowed. After the max number of tag values is reached, metrics with additional tag values are denied by filter.
management.metrics.web.client.record-request-percentiles=false # Whether instrumented requests record percentiles histogram buckets by default.