diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/pom.xml b/spring-boot-project/spring-boot-actuator-autoconfigure/pom.xml
index 5aea66cbc2..b4eb5f61a3 100644
--- a/spring-boot-project/spring-boot-actuator-autoconfigure/pom.xml
+++ b/spring-boot-project/spring-boot-actuator-autoconfigure/pom.xml
@@ -102,6 +102,11 @@
micrometer-registry-datadog
true
+
+ io.micrometer
+ micrometer-registry-dynatrace
+ true
+
io.micrometer
micrometer-registry-ganglia
diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/dynatrace/DynatraceMetricsExportAutoConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/dynatrace/DynatraceMetricsExportAutoConfiguration.java
new file mode 100644
index 0000000000..e9d28ae3f0
--- /dev/null
+++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/dynatrace/DynatraceMetricsExportAutoConfiguration.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.dynatrace;
+
+import io.micrometer.core.instrument.Clock;
+import io.micrometer.dynatrace.DynatraceConfig;
+import io.micrometer.dynatrace.DynatraceMeterRegistry;
+
+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 Dynatrace.
+ *
+ * @author Andy Wilkinson
+ * @since 2.1.0
+ */
+@Configuration
+@AutoConfigureBefore({ CompositeMeterRegistryAutoConfiguration.class,
+ SimpleMetricsExportAutoConfiguration.class })
+@AutoConfigureAfter(MetricsAutoConfiguration.class)
+@ConditionalOnBean(Clock.class)
+@ConditionalOnClass(DynatraceMeterRegistry.class)
+@ConditionalOnProperty(prefix = "management.metrics.export.dynatrace", name = "enabled", havingValue = "true", matchIfMissing = true)
+@EnableConfigurationProperties(DynatraceProperties.class)
+public class DynatraceMetricsExportAutoConfiguration {
+
+ @Bean
+ @ConditionalOnMissingBean
+ public DynatraceConfig dynatraceConfig(DynatraceProperties dynatraceProperties) {
+ return new DynatracePropertiesConfigAdapter(dynatraceProperties);
+ }
+
+ @Bean
+ @ConditionalOnMissingBean
+ public DynatraceMeterRegistry dynatraceMeterRegistry(DynatraceConfig dynatraceConfig,
+ Clock clock) {
+ return new DynatraceMeterRegistry(dynatraceConfig, clock);
+ }
+
+}
diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/dynatrace/DynatraceProperties.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/dynatrace/DynatraceProperties.java
new file mode 100644
index 0000000000..2be57720f0
--- /dev/null
+++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/dynatrace/DynatraceProperties.java
@@ -0,0 +1,85 @@
+/*
+ * 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.dynatrace;
+
+import org.springframework.boot.actuate.autoconfigure.metrics.export.properties.StepRegistryProperties;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+
+/**
+ * {@link ConfigurationProperties} for configuring Dynatrace metrics export.
+ *
+ * @author Andy Wilkinson
+ * @since 2.1.0
+ */
+@ConfigurationProperties(prefix = "management.metrics.export.dynatrace")
+public class DynatraceProperties extends StepRegistryProperties {
+
+ /**
+ * Dynatrace authentication token.
+ */
+ private String apiToken;
+
+ /**
+ * ID of the custom device that is exporting metrics to Dynatrace.
+ */
+ private String deviceId;
+
+ /**
+ * Technology type for exported metrics. Used to group metrics under a logical
+ * technology name in the Dynatrace UI.
+ */
+ private String technologyType = "java";
+
+ /**
+ * URI to ship metrics to. If you need to publish metrics to an internal proxy
+ * en-route to Dynatrace, you can define the location of the proxy with this.
+ */
+ private String uri;
+
+ public String getApiToken() {
+ return this.apiToken;
+ }
+
+ public void setApiToken(String apiToken) {
+ this.apiToken = apiToken;
+ }
+
+ public String getDeviceId() {
+ return this.deviceId;
+ }
+
+ public void setDeviceId(String deviceId) {
+ this.deviceId = deviceId;
+ }
+
+ public String getTechnologyType() {
+ return this.technologyType;
+ }
+
+ public void setTechnologyType(String technologyType) {
+ this.technologyType = technologyType;
+ }
+
+ public String getUri() {
+ return this.uri;
+ }
+
+ public void setUri(String uri) {
+ this.uri = uri;
+ }
+
+}
diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/dynatrace/DynatracePropertiesConfigAdapter.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/dynatrace/DynatracePropertiesConfigAdapter.java
new file mode 100644
index 0000000000..099877457f
--- /dev/null
+++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/dynatrace/DynatracePropertiesConfigAdapter.java
@@ -0,0 +1,58 @@
+/*
+ * 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.dynatrace;
+
+import io.micrometer.datadog.DatadogConfig;
+import io.micrometer.dynatrace.DynatraceConfig;
+
+import org.springframework.boot.actuate.autoconfigure.metrics.export.properties.StepRegistryPropertiesConfigAdapter;
+
+/**
+ * Adapter to convert {@link DynatraceProperties} to a {@link DatadogConfig}.
+ *
+ * @author Andy Wilkinson *
+ */
+class DynatracePropertiesConfigAdapter
+ extends StepRegistryPropertiesConfigAdapter
+ implements DynatraceConfig {
+
+ DynatracePropertiesConfigAdapter(DynatraceProperties properties) {
+ super(properties);
+ }
+
+ @Override
+ public String apiToken() {
+ return get(DynatraceProperties::getApiToken, DynatraceConfig.super::apiToken);
+ }
+
+ @Override
+ public String deviceId() {
+ return get(DynatraceProperties::getDeviceId, DynatraceConfig.super::deviceId);
+ }
+
+ @Override
+ public String technologyType() {
+ return get(DynatraceProperties::getTechnologyType,
+ DynatraceConfig.super::technologyType);
+ }
+
+ @Override
+ public String uri() {
+ return get(DynatraceProperties::getUri, DynatraceConfig.super::uri);
+ }
+
+}
diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/dynatrace/package-info.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/dynatrace/package-info.java
new file mode 100644
index 0000000000..36e019707b
--- /dev/null
+++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/dynatrace/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 Dynatrace.
+ */
+package org.springframework.boot.actuate.autoconfigure.metrics.export.dynatrace;
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 0109c40f12..dbbf947272 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
@@ -43,6 +43,7 @@ org.springframework.boot.actuate.autoconfigure.metrics.amqp.RabbitMetricsAutoCon
org.springframework.boot.actuate.autoconfigure.metrics.cache.CacheMetricsAutoConfiguration,\
org.springframework.boot.actuate.autoconfigure.metrics.export.atlas.AtlasMetricsExportAutoConfiguration,\
org.springframework.boot.actuate.autoconfigure.metrics.export.datadog.DatadogMetricsExportAutoConfiguration,\
+org.springframework.boot.actuate.autoconfigure.metrics.export.dynatrace.DynatraceMetricsExportAutoConfiguration,\
org.springframework.boot.actuate.autoconfigure.metrics.export.ganglia.GangliaMetricsExportAutoConfiguration,\
org.springframework.boot.actuate.autoconfigure.metrics.export.graphite.GraphiteMetricsExportAutoConfiguration,\
org.springframework.boot.actuate.autoconfigure.metrics.export.influx.InfluxMetricsExportAutoConfiguration,\
diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/export/dynatrace/DynatraceMetricsExportAutoConfigurationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/export/dynatrace/DynatraceMetricsExportAutoConfigurationTests.java
new file mode 100644
index 0000000000..7d307594be
--- /dev/null
+++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/export/dynatrace/DynatraceMetricsExportAutoConfigurationTests.java
@@ -0,0 +1,169 @@
+/*
+ * 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.dynatrace;
+
+import java.util.Map;
+
+import io.micrometer.core.instrument.Clock;
+import io.micrometer.dynatrace.DynatraceConfig;
+import io.micrometer.dynatrace.DynatraceMeterRegistry;
+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 DynatraceMetricsExportAutoConfiguration}.
+ *
+ * @author Andy Wilkinson
+ */
+public class DynatraceMetricsExportAutoConfigurationTests {
+
+ private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
+ .withConfiguration(
+ AutoConfigurations.of(DynatraceMetricsExportAutoConfiguration.class));
+
+ @Test
+ public void backsOffWithoutAClock() {
+ this.contextRunner.run((context) -> assertThat(context)
+ .doesNotHaveBean(DynatraceMeterRegistry.class));
+ }
+
+ @Test
+ public void failsWithoutAUri() {
+ this.contextRunner.withUserConfiguration(BaseConfiguration.class)
+ .run((context) -> assertThat(context).hasFailed());
+ }
+
+ @Test
+ public void autoConfiguresConfigAndMeterRegistry() {
+ this.contextRunner.withUserConfiguration(BaseConfiguration.class)
+ .withPropertyValues(
+ "management.metrics.export.dynatrace.uri=https://dynatrace.example.com")
+ .run((context) -> assertThat(context)
+ .hasSingleBean(DynatraceMeterRegistry.class)
+ .hasSingleBean(DynatraceConfig.class));
+ }
+
+ @Test
+ public void autoConfigurationCanBeDisabled() {
+ this.contextRunner.withUserConfiguration(BaseConfiguration.class)
+ .withPropertyValues("management.metrics.export.dynatrace.enabled=false")
+ .run((context) -> assertThat(context)
+ .doesNotHaveBean(DynatraceMeterRegistry.class)
+ .doesNotHaveBean(DynatraceConfig.class));
+ }
+
+ @Test
+ public void allowsCustomConfigToBeUsed() {
+ this.contextRunner.withUserConfiguration(CustomConfigConfiguration.class)
+ .run((context) -> assertThat(context)
+ .hasSingleBean(DynatraceMeterRegistry.class)
+ .hasSingleBean(DynatraceConfig.class).hasBean("customConfig"));
+ }
+
+ @Test
+ public void allowsCustomRegistryToBeUsed() {
+ this.contextRunner.withUserConfiguration(CustomRegistryConfiguration.class)
+ .withPropertyValues(
+ "management.metrics.export.dynatrace.uri=https://dynatrace.example.com")
+ .run((context) -> assertThat(context)
+ .hasSingleBean(DynatraceMeterRegistry.class)
+ .hasBean("customRegistry").hasSingleBean(DynatraceConfig.class));
+ }
+
+ @Test
+ public void stopsMeterRegistryWhenContextIsClosed() {
+ this.contextRunner.withUserConfiguration(BaseConfiguration.class)
+ .withPropertyValues("management.metrics.export.dynatrace.api-token=abcde",
+ "management.metrics.export.dynatrace.uri=https://dynatrace.example.com",
+ "management.metrics.export.dynatrace.deviceId=test")
+ .run((context) -> {
+ DynatraceMeterRegistry registry = spyOnDisposableBean(
+ DynatraceMeterRegistry.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 DynatraceConfig customConfig() {
+ return new DynatraceConfig() {
+
+ @Override
+ public String get(String k) {
+ if ("dynatrace.uri".equals(k)) {
+ return "https://dynatrace.example.com";
+ }
+ return null;
+ }
+
+ };
+ }
+
+ }
+
+ @Configuration
+ @Import(BaseConfiguration.class)
+ static class CustomRegistryConfiguration {
+
+ @Bean
+ public DynatraceMeterRegistry customRegistry(DynatraceConfig config,
+ Clock clock) {
+ return new DynatraceMeterRegistry(config, clock);
+ }
+
+ }
+
+}
diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/export/dynatrace/DynatracePropertiesConfigAdapterTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/export/dynatrace/DynatracePropertiesConfigAdapterTests.java
new file mode 100644
index 0000000000..b8e6e6e9c1
--- /dev/null
+++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/export/dynatrace/DynatracePropertiesConfigAdapterTests.java
@@ -0,0 +1,62 @@
+/*
+ * 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.dynatrace;
+
+import org.junit.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Tests for {@link DynatracePropertiesConfigAdapter}.
+ *
+ * @author Andy Wilkiknson
+ */
+public class DynatracePropertiesConfigAdapterTests {
+
+ @Test
+ public void whenPropertiesUriIsSetAdapterUriReturnsIt() {
+ DynatraceProperties properties = new DynatraceProperties();
+ properties.setUri("https://dynatrace.example.com");
+ assertThat(new DynatracePropertiesConfigAdapter(properties).uri())
+ .isEqualTo("https://dynatrace.example.com");
+ }
+
+ @Test
+ public void whenPropertiesApiTokenIsSetAdapterApiTokenReturnsIt() {
+ DynatraceProperties properties = new DynatraceProperties();
+ properties.setApiToken("123ABC");
+ assertThat(new DynatracePropertiesConfigAdapter(properties).apiToken())
+ .isEqualTo("123ABC");
+ }
+
+ @Test
+ public void whenPropertiesDeviceIdIsSetAdapterDeviceIdReturnsIt() {
+ DynatraceProperties properties = new DynatraceProperties();
+ properties.setDeviceId("dev-1");
+ assertThat(new DynatracePropertiesConfigAdapter(properties).deviceId())
+ .isEqualTo("dev-1");
+ }
+
+ @Test
+ public void whenPropertiesTechnologyTypeIsSetAdapterTechnologyTypeReturnsIt() {
+ DynatraceProperties properties = new DynatraceProperties();
+ properties.setTechnologyType("tech-1");
+ assertThat(new DynatracePropertiesConfigAdapter(properties).technologyType())
+ .isEqualTo("tech-1");
+ }
+
+}
diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/export/dynatrace/DynatracePropertiesTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/export/dynatrace/DynatracePropertiesTests.java
new file mode 100644
index 0000000000..b360f258e1
--- /dev/null
+++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/export/dynatrace/DynatracePropertiesTests.java
@@ -0,0 +1,40 @@
+/*
+ * 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.dynatrace;
+
+import io.micrometer.dynatrace.DynatraceConfig;
+
+import org.springframework.boot.actuate.autoconfigure.metrics.export.properties.StepRegistryPropertiesTests;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Tests for {@link DynatraceProperties}.
+ *
+ * @author Andy Wilkinson
+ */
+public class DynatracePropertiesTests extends StepRegistryPropertiesTests {
+
+ @Override
+ public void defaultValuesAreConsistent() {
+ DynatraceProperties properties = new DynatraceProperties();
+ DynatraceConfig config = DynatraceConfig.DEFAULT;
+ assertStepRegistryDefaultValues(properties, config);
+ assertThat(properties.getTechnologyType()).isEqualTo(config.technologyType());
+ }
+
+}
diff --git a/spring-boot-project/spring-boot-dependencies/pom.xml b/spring-boot-project/spring-boot-dependencies/pom.xml
index d291edfe52..716ff1fdf2 100644
--- a/spring-boot-project/spring-boot-dependencies/pom.xml
+++ b/spring-boot-project/spring-boot-dependencies/pom.xml
@@ -899,6 +899,11 @@
micrometer-registry-datadog
${micrometer.version}
+
+ io.micrometer
+ micrometer-registry-dynatrace
+ ${micrometer.version}
+
io.micrometer
micrometer-registry-influx
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 1fc1d2feb0..4780209a0e 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
@@ -1400,6 +1400,16 @@ content into your application. Rather, pick only the properties that you need.
management.metrics.export.datadog.read-timeout=10s # Read timeout for requests to this backend.
management.metrics.export.datadog.step=1m # Step size (i.e. reporting frequency) to use.
management.metrics.export.datadog.uri=https://app.datadoghq.com # URI to ship metrics to. If you need to publish metrics to an internal proxy en-route to Datadog, you can define the location of the proxy with this.
+ management.metrics.export.dynatrace.api-token= # Dynatrace API token.
+ management.metrics.export.dynatrace.batch-size=10000 # Number of measurements per request to use for this backend. If more measurements are found, then multiple requests will be made.
+ management.metrics.export.dynatrace.connect-timeout=1s # Connection timeout for requests to this backend.
+ management.metrics.export.dynatrace.deviceId= # ID of the custom device that is exporting metrics to Dynatrace.
+ management.metrics.export.dynatrace.enabled=true # Whether exporting of metrics to this backend is enabled.
+ management.metrics.export.dynatrace.num-threads=2 # Number of threads to use with the metrics publishing scheduler.
+ management.metrics.export.dynatrace.read-timeout=10s # Read timeout for requests to this backend.
+ management.metrics.export.dynatrace.step=1m # Step size (i.e. reporting frequency) to use.
+ management.metrics.export.dynatrace.technology-type=java # Technology type for exported metrics. Used to group metrics under a logical technology name in the Dynatrace UI.
+ management.metrics.export.dynatrace.uri= # URI to ship metrics to. If you need to publish metrics to an internal proxy en-route to Dynatrace, you can define the location of the proxy with this.
management.metrics.export.ganglia.addressing-mode=multicast # UDP addressing mode, either unicast or multicast.
management.metrics.export.ganglia.duration-units=milliseconds # Base time unit used to report durations.
management.metrics.export.ganglia.enabled=true # Whether exporting of metrics to Ganglia is enabled.
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 3671d5e8ea..eea3521e14 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
@@ -1336,6 +1336,7 @@ monitoring systems, including:
- <>
- <>
+- <>
- <>
- <>
- <>
@@ -1452,6 +1453,28 @@ You can also change the interval at which metrics are sent to Datadog:
+[[production-ready-metrics-export-dynatrace]]
+==== Datadog
+Dynatrace registry pushes metrics to the configured UIR periodically. To export metrics to
+{micrometer-registry-documentation}/dynatrace[Dynatrace], your API token, device ID, and
+URI must be provided:
+
+[source,properties,indent=0]
+----
+ management.metrics.export.dynatrace.api-token=YOUR_TOKEN
+ management.metrics.export.dynatrace.device-id=YOUR_DEVICE_ID
+ management.metrics.export.dynatrace.uri=YOUR_URI
+----
+
+You can also change the interval at which metrics are sent to Dynatrace:
+
+[source,properties,indent=0]
+----
+ management.metrics.export.dynatrace.step=30s
+----
+
+
+
[[production-ready-metrics-export-ganglia]]
==== Ganglia
By default, metrics are exported to {micrometer-registry-documentation}/ganglia[Ganglia]