diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/pom.xml b/spring-boot-project/spring-boot-actuator-autoconfigure/pom.xml
index 3768e9f4f2..aa824b2ae1 100644
--- a/spring-boot-project/spring-boot-actuator-autoconfigure/pom.xml
+++ b/spring-boot-project/spring-boot-actuator-autoconfigure/pom.xml
@@ -174,6 +174,11 @@
micrometer-registry-signalfx
true
+
+ io.micrometer
+ micrometer-registry-stackdriver
+ true
+
io.micrometer
micrometer-registry-statsd
diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/stackdriver/StackdriverMetricsExportAutoConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/stackdriver/StackdriverMetricsExportAutoConfiguration.java
new file mode 100644
index 0000000000..b3d9a20a3f
--- /dev/null
+++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/stackdriver/StackdriverMetricsExportAutoConfiguration.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2012-2020 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
+ *
+ * https://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.stackdriver;
+
+import io.micrometer.core.instrument.Clock;
+import io.micrometer.stackdriver.StackdriverConfig;
+import io.micrometer.stackdriver.StackdriverMeterRegistry;
+
+import org.springframework.boot.actuate.autoconfigure.metrics.CompositeMeterRegistryAutoConfiguration;
+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
+ * Stackdriver.
+ *
+ * @author Johannes Graf
+ * @author Stephane Nicoll
+ * @since 2.3.0
+ */
+@Configuration(proxyBeanMethods = false)
+@AutoConfigureBefore({ CompositeMeterRegistryAutoConfiguration.class, SimpleMetricsExportAutoConfiguration.class })
+@AutoConfigureAfter(MetricsAutoConfiguration.class)
+@ConditionalOnBean(Clock.class)
+@ConditionalOnClass(StackdriverMeterRegistry.class)
+@ConditionalOnProperty(prefix = "management.metrics.export.stackdriver", name = "enabled", havingValue = "true",
+ matchIfMissing = true)
+@EnableConfigurationProperties(StackdriverProperties.class)
+public class StackdriverMetricsExportAutoConfiguration {
+
+ private final StackdriverProperties properties;
+
+ public StackdriverMetricsExportAutoConfiguration(StackdriverProperties stackdriverProperties) {
+ this.properties = stackdriverProperties;
+ }
+
+ @Bean
+ @ConditionalOnMissingBean
+ public StackdriverConfig stackdriverConfig() {
+ return new StackdriverPropertiesConfigAdapter(this.properties);
+ }
+
+ @Bean
+ @ConditionalOnMissingBean
+ public StackdriverMeterRegistry stackdriverMeterRegistry(StackdriverConfig stackdriverConfig, Clock clock) {
+ return StackdriverMeterRegistry.builder(stackdriverConfig).clock(clock).build();
+ }
+
+}
diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/stackdriver/StackdriverProperties.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/stackdriver/StackdriverProperties.java
new file mode 100644
index 0000000000..07c6668244
--- /dev/null
+++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/stackdriver/StackdriverProperties.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2012-2020 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
+ *
+ * https://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.stackdriver;
+
+import org.springframework.boot.actuate.autoconfigure.metrics.export.properties.StepRegistryProperties;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+
+/**
+ * {@link ConfigurationProperties @ConfigurationProperties} for configuring Stackdriver
+ * metrics export.
+ *
+ * @author Johannes Graf
+ * @author Stephane Nicoll
+ * @since 2.3.0
+ */
+@ConfigurationProperties(prefix = "management.metrics.export.stackdriver")
+public class StackdriverProperties extends StepRegistryProperties {
+
+ /**
+ * Identifier of the Google Cloud project to monitor.
+ */
+ private String projectId;
+
+ /**
+ * Monitored resource type.
+ */
+ private String resourceType = "global";
+
+ public String getProjectId() {
+ return this.projectId;
+ }
+
+ public void setProjectId(String projectId) {
+ this.projectId = projectId;
+ }
+
+ public String getResourceType() {
+ return this.resourceType;
+ }
+
+ public void setResourceType(String resourceType) {
+ this.resourceType = resourceType;
+ }
+
+}
diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/stackdriver/StackdriverPropertiesConfigAdapter.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/stackdriver/StackdriverPropertiesConfigAdapter.java
new file mode 100644
index 0000000000..9b14af43f7
--- /dev/null
+++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/stackdriver/StackdriverPropertiesConfigAdapter.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2012-2020 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
+ *
+ * https://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.stackdriver;
+
+import io.micrometer.stackdriver.StackdriverConfig;
+
+import org.springframework.boot.actuate.autoconfigure.metrics.export.properties.StepRegistryPropertiesConfigAdapter;
+
+/**
+ * Adapter to convert {@link StackdriverProperties} to a {@link StackdriverConfig}.
+ *
+ * @author Johannes Graf
+ * @since 2.3.0
+ */
+public class StackdriverPropertiesConfigAdapter extends StepRegistryPropertiesConfigAdapter
+ implements StackdriverConfig {
+
+ public StackdriverPropertiesConfigAdapter(StackdriverProperties properties) {
+ super(properties);
+ }
+
+ @Override
+ public String projectId() {
+ return get(StackdriverProperties::getProjectId, StackdriverConfig.super::projectId);
+ }
+
+ @Override
+ public String resourceType() {
+ return get(StackdriverProperties::getResourceType, StackdriverConfig.super::resourceType);
+ }
+
+}
diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/stackdriver/package-info.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/stackdriver/package-info.java
new file mode 100644
index 0000000000..df40a7adb9
--- /dev/null
+++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/stackdriver/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2012-2020 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
+ *
+ * https://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 Stackdriver.
+ */
+package org.springframework.boot.actuate.autoconfigure.metrics.export.stackdriver;
diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/export/stackdriver/StackdriverMetricsExportAutoConfigurationTest.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/export/stackdriver/StackdriverMetricsExportAutoConfigurationTest.java
new file mode 100644
index 0000000000..ae9182774e
--- /dev/null
+++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/export/stackdriver/StackdriverMetricsExportAutoConfigurationTest.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright 2012-2020 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
+ *
+ * https://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.stackdriver;
+
+import io.micrometer.core.instrument.Clock;
+import io.micrometer.stackdriver.StackdriverConfig;
+import io.micrometer.stackdriver.StackdriverMeterRegistry;
+import org.junit.jupiter.api.Test;
+
+import org.springframework.boot.autoconfigure.AutoConfigurations;
+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 static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Tests for {@link StackdriverMetricsExportAutoConfiguration}.
+ *
+ * @author Johannes Graf
+ */
+class StackdriverMetricsExportAutoConfigurationTest {
+
+ private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
+ .withConfiguration(AutoConfigurations.of(StackdriverMetricsExportAutoConfiguration.class));
+
+ @Test
+ void backsOffWithoutAClock() {
+ this.contextRunner.run((context) -> assertThat(context).doesNotHaveBean(StackdriverMeterRegistry.class));
+ }
+
+ @Test
+ void failsWithoutAnProjectId() {
+ this.contextRunner.withUserConfiguration(BaseConfiguration.class)
+ .run((context) -> assertThat(context).hasFailed());
+ }
+
+ @Test
+ void autoConfiguresConfigAndMeterRegistry() {
+ this.contextRunner.withUserConfiguration(BaseConfiguration.class)
+ .withPropertyValues("management.metrics.export.stackdriver.project-id=test-project")
+ .run((context) -> assertThat(context).hasSingleBean(StackdriverMeterRegistry.class)
+ .hasSingleBean(StackdriverConfig.class));
+ }
+
+ @Test
+ void autoConfigurationCanBeDisabled() {
+ this.contextRunner.withUserConfiguration(BaseConfiguration.class)
+ .withPropertyValues("management.metrics.export.stackdriver.enabled=false")
+ .run((context) -> assertThat(context).doesNotHaveBean(StackdriverMeterRegistry.class)
+ .doesNotHaveBean(StackdriverConfig.class));
+ }
+
+ @Test
+ void allowsCustomConfigToBeUsed() {
+ this.contextRunner.withUserConfiguration(CustomConfigConfiguration.class)
+ .run((context) -> assertThat(context).hasSingleBean(StackdriverMeterRegistry.class)
+ .hasSingleBean(StackdriverConfig.class).hasBean("customConfig"));
+ }
+
+ @Test
+ void allowsCustomRegistryToBeUsed() {
+ this.contextRunner.withUserConfiguration(CustomRegistryConfiguration.class)
+ .withPropertyValues("management.metrics.export.stackdriver.project-id=test-project")
+ .run((context) -> assertThat(context).hasSingleBean(StackdriverMeterRegistry.class)
+ .hasBean("customRegistry").hasSingleBean(StackdriverConfig.class));
+ }
+
+ @Test
+ void stopsMeterRegistryWhenContextIsClosed() {
+ this.contextRunner.withUserConfiguration(BaseConfiguration.class)
+ .withPropertyValues("management.metrics.export.stackdriver.project-id=test-project").run((context) -> {
+ StackdriverMeterRegistry registry = context.getBean(StackdriverMeterRegistry.class);
+ assertThat(registry.isClosed()).isFalse();
+ context.close();
+ assertThat(registry.isClosed()).isTrue();
+ });
+ }
+
+ @Configuration(proxyBeanMethods = false)
+ static class BaseConfiguration {
+
+ @Bean
+ Clock clock() {
+ return Clock.SYSTEM;
+ }
+
+ }
+
+ @Configuration(proxyBeanMethods = false)
+ @Import(BaseConfiguration.class)
+ static class CustomConfigConfiguration {
+
+ @Bean
+ StackdriverConfig customConfig() {
+ return (key) -> {
+ if ("stackdriver.projectId".equals(key)) {
+ return "test-project";
+ }
+ return null;
+ };
+ }
+
+ }
+
+ @Configuration(proxyBeanMethods = false)
+ @Import(BaseConfiguration.class)
+ static class CustomRegistryConfiguration {
+
+ @Bean
+ StackdriverMeterRegistry customRegistry(StackdriverConfig config, Clock clock) {
+ return new StackdriverMeterRegistry(config, clock);
+ }
+
+ }
+
+}
diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/export/stackdriver/StackdriverPropertiesConfigAdapterTest.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/export/stackdriver/StackdriverPropertiesConfigAdapterTest.java
new file mode 100644
index 0000000000..6eb3650e96
--- /dev/null
+++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/export/stackdriver/StackdriverPropertiesConfigAdapterTest.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2012-2020 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
+ *
+ * https://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.stackdriver;
+
+import org.junit.jupiter.api.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Tests for {@link StackdriverPropertiesConfigAdapter}.
+ *
+ * @author Johannes Graf
+ */
+class StackdriverPropertiesConfigAdapterTest {
+
+ @Test
+ void whenPropertiesProjectIdIsSetAdapterProjectIdReturnsIt() {
+ StackdriverProperties properties = new StackdriverProperties();
+ properties.setProjectId("my-gcp-project-id");
+ assertThat(new StackdriverPropertiesConfigAdapter(properties).projectId()).isEqualTo("my-gcp-project-id");
+ }
+
+ @Test
+ void whenPropertiesResourceTypeIsSetAdapterResourceTypeReturnsIt() {
+ StackdriverProperties properties = new StackdriverProperties();
+ properties.setResourceType("my-resource-type");
+ assertThat(new StackdriverPropertiesConfigAdapter(properties).resourceType()).isEqualTo("my-resource-type");
+ }
+
+}
diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/export/stackdriver/StackdriverPropertiesTest.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/export/stackdriver/StackdriverPropertiesTest.java
new file mode 100644
index 0000000000..89c16cb9c0
--- /dev/null
+++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/export/stackdriver/StackdriverPropertiesTest.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2012-2020 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
+ *
+ * https://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.stackdriver;
+
+import io.micrometer.stackdriver.StackdriverConfig;
+import org.junit.jupiter.api.Test;
+
+import org.springframework.boot.actuate.autoconfigure.metrics.export.properties.StepRegistryPropertiesTests;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Tests for {@link StackdriverProperties}.
+ *
+ * @author Johannes Graf
+ */
+class StackdriverPropertiesTest extends StepRegistryPropertiesTests {
+
+ @Test
+ void defaultValuesAreConsistent() {
+ StackdriverProperties properties = new StackdriverProperties();
+ StackdriverConfig config = (key) -> null;
+ assertStepRegistryDefaultValues(properties, config);
+ assertThat(properties.getResourceType()).isEqualTo(config.resourceType());
+ }
+
+}
diff --git a/spring-boot-project/spring-boot-dependencies/pom.xml b/spring-boot-project/spring-boot-dependencies/pom.xml
index 38c72904ff..ce2763d9eb 100644
--- a/spring-boot-project/spring-boot-dependencies/pom.xml
+++ b/spring-boot-project/spring-boot-dependencies/pom.xml
@@ -1038,6 +1038,17 @@
lettuce-core
${lettuce.version}
+
+ io.micrometer
+ micrometer-registry-stackdriver
+ ${micrometer.version}
+
+
+ javax.annotation
+ javax.annotation-api
+
+
+
io.micrometer
micrometer-bom
diff --git a/spring-boot-project/spring-boot-docs/src/main/asciidoc/production-ready-features.adoc b/spring-boot-project/spring-boot-docs/src/main/asciidoc/production-ready-features.adoc
index 24fd61b032..1537c2f4f6 100644
--- a/spring-boot-project/spring-boot-docs/src/main/asciidoc/production-ready-features.adoc
+++ b/spring-boot-project/spring-boot-docs/src/main/asciidoc/production-ready-features.adoc
@@ -1245,6 +1245,7 @@ Spring Boot Actuator provides dependency management and auto-configuration for h
- <>
- <>
- <>
+- <>
- <>
- <>
@@ -1584,6 +1585,25 @@ You can also disable it explicitly:
+[[production-ready-metrics-export-stackdriver]]
+==== Stackdriver
+Stackdriver registry pushes metrics to https://cloud.google.com/stackdriver/[Stackdriver] periodically.
+To export metrics to SaaS {micrometer-registry-docs}/stackdriver[Stackdriver], your Google Cloud project id must be provided:
+
+[source,properties,indent=0,configprops]
+----
+ management.metrics.export.stackdriver.project-id=my-project
+----
+
+You can also change the interval at which metrics are sent to Stackdriver:
+
+[source,properties,indent=0,configprops]
+----
+ management.metrics.export.stackdriver.step=30s
+----
+
+
+
[[production-ready-metrics-export-statsd]]
==== StatsD
The StatsD registry pushes metrics over UDP to a StatsD agent eagerly.