From 316116491231172016a1c33a035f7d24845e708d Mon Sep 17 00:00:00 2001 From: Georg Pirklbauer Date: Mon, 19 Apr 2021 10:33:10 +0200 Subject: [PATCH 1/4] Add properties for Dynatrace metrics API v2 ingest with Micrometer --- .../export/dynatrace/DynatraceProperties.java | 76 ++++++++++++++++++ .../DynatracePropertiesConfigAdapter.java | 24 ++++++ ...DynatracePropertiesConfigAdapterTests.java | 54 +++++++++++++ .../src/docs/asciidoc/actuator/metrics.adoc | 79 +++++++++++++++++-- 4 files changed, 228 insertions(+), 5 deletions(-) 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 index 58d6d13ad4..297457d89a 100644 --- 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 @@ -16,6 +16,10 @@ package org.springframework.boot.actuate.autoconfigure.metrics.export.dynatrace; +import java.util.Map; + +import io.micrometer.dynatrace.DynatraceApiVersion; + import org.springframework.boot.actuate.autoconfigure.metrics.export.properties.StepRegistryProperties; import org.springframework.boot.context.properties.ConfigurationProperties; @@ -24,39 +28,79 @@ import org.springframework.boot.context.properties.ConfigurationProperties; * metrics export. * * @author Andy Wilkinson + * @author Georg Pirklbauer * @since 2.1.0 */ @ConfigurationProperties(prefix = "management.metrics.export.dynatrace") public class DynatraceProperties extends StepRegistryProperties { + /** + * The Dynatrace metrics API version that metrics should be sent to. Defaults to v1. + * Required to define which API is used for export. + */ + private DynatraceApiVersion apiVersion = DynatraceApiVersion.V1; + /** * Dynatrace authentication token. + * + * API v1: required, API v2: optional */ private String apiToken; /** * ID of the custom device that is exporting metrics to Dynatrace. + * + * API v1: required, API v2: not applicable (ignored) */ private String deviceId; /** * Technology type for exported metrics. Used to group metrics under a logical * technology name in the Dynatrace UI. + * + * API v1: required, API v2: not applicable (ignored) */ private String technologyType = "java"; /** * URI to ship metrics to. Should be used for SaaS, self managed instances or to * en-route through an internal proxy. + * + * API v1: required, API v2: optional */ private String uri; /** * Group for exported metrics. Used to specify custom device group name in the * Dynatrace UI. + * + * API v1: required, API v2: not applicable (ignored) */ private String group; + /** + * An optional prefix string that is added to all metrics exported. + * + * API v1: not applicable (ignored), API v2: optional + */ + private String metricKeyPrefix; + + /** + * An optional Boolean that allows enabling of the Dynatrace metadata export. On by + * default. + * + * API v1: not applicable (ignored), API v2: optional + */ + private Boolean enrichWithDynatraceMetadata = true; + + /** + * Optional default dimensions that are added to all metrics in the form of key-value + * pairs. These are overwritten by Micrometer tags if they use the same key. + * + * API v1: not applicable (ignored), API v2: optional + */ + private Map defaultDimensions; + public String getApiToken() { return this.apiToken; } @@ -97,4 +141,36 @@ public class DynatraceProperties extends StepRegistryProperties { this.group = group; } + public String getMetricKeyPrefix() { + return this.metricKeyPrefix; + } + + public void setMetricKeyPrefix(String metricKeyPrefix) { + this.metricKeyPrefix = metricKeyPrefix; + } + + public Boolean getEnrichWithDynatraceMetadata() { + return this.enrichWithDynatraceMetadata; + } + + public void setEnrichWithDynatraceMetadata(Boolean enrichWithDynatraceMetadata) { + this.enrichWithDynatraceMetadata = enrichWithDynatraceMetadata; + } + + public Map getDefaultDimensions() { + return this.defaultDimensions; + } + + public void setDefaultDimensions(Map defaultDimensions) { + this.defaultDimensions = defaultDimensions; + } + + public DynatraceApiVersion getApiVersion() { + return this.apiVersion; + } + + public void setApiVersion(DynatraceApiVersion apiVersion) { + this.apiVersion = apiVersion; + } + } 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 index 6d7444ce82..7e232ffe0e 100644 --- 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 @@ -16,6 +16,9 @@ package org.springframework.boot.actuate.autoconfigure.metrics.export.dynatrace; +import java.util.Map; + +import io.micrometer.dynatrace.DynatraceApiVersion; import io.micrometer.dynatrace.DynatraceConfig; import org.springframework.boot.actuate.autoconfigure.metrics.export.properties.StepRegistryPropertiesConfigAdapter; @@ -24,6 +27,7 @@ import org.springframework.boot.actuate.autoconfigure.metrics.export.properties. * Adapter to convert {@link DynatraceProperties} to a {@link DynatraceConfig}. * * @author Andy Wilkinson + * @author Georg Pirklbauer */ class DynatracePropertiesConfigAdapter extends StepRegistryPropertiesConfigAdapter implements DynatraceConfig { @@ -62,4 +66,24 @@ class DynatracePropertiesConfigAdapter extends StepRegistryPropertiesConfigAdapt return get(DynatraceProperties::getGroup, DynatraceConfig.super::group); } + @Override + public DynatraceApiVersion apiVersion() { + return get(DynatraceProperties::getApiVersion, DynatraceConfig.super::apiVersion); + } + + @Override + public String metricKeyPrefix() { + return get(DynatraceProperties::getMetricKeyPrefix, DynatraceConfig.super::metricKeyPrefix); + } + + @Override + public Map defaultDimensions() { + return get(DynatraceProperties::getDefaultDimensions, DynatraceConfig.super::defaultDimensions); + } + + @Override + public boolean enrichWithDynatraceMetadata() { + return get(DynatraceProperties::getEnrichWithDynatraceMetadata, + DynatraceConfig.super::enrichWithDynatraceMetadata); + } } 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 index 8a4b25b079..74aaa5e454 100644 --- 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 @@ -16,6 +16,9 @@ package org.springframework.boot.actuate.autoconfigure.metrics.export.dynatrace; +import java.util.HashMap; + +import io.micrometer.dynatrace.DynatraceApiVersion; import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThat; @@ -24,6 +27,7 @@ import static org.assertj.core.api.Assertions.assertThat; * Tests for {@link DynatracePropertiesConfigAdapter}. * * @author Andy Wilkinson + * @author Georg Pirklbauer */ class DynatracePropertiesConfigAdapterTests { @@ -62,4 +66,54 @@ class DynatracePropertiesConfigAdapterTests { assertThat(new DynatracePropertiesConfigAdapter(properties).group()).isEqualTo("group-1"); } + @Test + void whenPropertiesApiVersionIsSetAdapterGroupReturnsIt() { + DynatraceProperties properties = new DynatraceProperties(); + properties.setApiVersion(DynatraceApiVersion.V1); + assertThat(new DynatracePropertiesConfigAdapter(properties).apiVersion()).isSameAs(DynatraceApiVersion.V1); + } + + @Test + void whenPropertiesMetricKeyPrefixIsSetAdapterGroupReturnsIt() { + DynatraceProperties properties = new DynatraceProperties(); + properties.setMetricKeyPrefix("my.prefix"); + assertThat(new DynatracePropertiesConfigAdapter(properties).metricKeyPrefix()).isEqualTo("my.prefix"); + } + + @Test + void whenPropertiesEnrichWithOneAgentMetadataIsSetAdapterGroupReturnsIt() { + DynatraceProperties properties = new DynatraceProperties(); + properties.setEnrichWithDynatraceMetadata(true); + assertThat(new DynatracePropertiesConfigAdapter(properties).enrichWithDynatraceMetadata()).isTrue(); + } + + @Test + void whenPropertiesDefaultDimensionsIsSetAdapterGroupReturnsIt() { + DynatraceProperties properties = new DynatraceProperties(); + HashMap defaultDimensions = new HashMap() { + { + put("dim1", "value1"); + put("dim2", "value2"); + } + }; + + properties.setDefaultDimensions(defaultDimensions); + assertThat(new DynatracePropertiesConfigAdapter(properties).defaultDimensions()) + .containsExactlyEntriesOf(defaultDimensions); + } + + @Test + void defaultValues() { + DynatraceProperties properties = new DynatraceProperties(); + assertThat(properties.getApiToken()).isNull(); + assertThat(properties.getDeviceId()).isNull(); + assertThat(properties.getTechnologyType()).isEqualTo("java"); + assertThat(properties.getUri()).isNull(); + assertThat(properties.getGroup()).isNull(); + assertThat(properties.getApiVersion()).isSameAs(DynatraceApiVersion.V1); + assertThat(properties.getMetricKeyPrefix()).isNull(); + assertThat(properties.getEnrichWithDynatraceMetadata()).isTrue(); + assertThat(properties.getDefaultDimensions()).isNull(); + } + } diff --git a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/actuator/metrics.adoc b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/actuator/metrics.adoc index 5a942ac413..6187617337 100644 --- a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/actuator/metrics.adoc +++ b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/actuator/metrics.adoc @@ -147,8 +147,72 @@ You can also change the interval at which metrics are sent to Datadog: [[actuator.metrics.export.dynatrace]] ==== Dynatrace -Dynatrace registry pushes metrics to the configured URI periodically. + +Dynatrace offers two metrics ingest APIs, both of which are implemented for {micrometer-registry-docs}/dynatrace[Micrometer]: + +[[actuator.metrics.export.dynatrace.api-v2]] +===== API v2 + +The API v2 can be used in two ways: + +If a local OneAgent is running on the host, it is enough to set the API version to v2 and metrics will be automatically exported to the https://www.dynatrace.com/support/help/how-to-use-dynatrace/metrics/metric-ingestion/ingestion-methods/local-api/[local OneAgent ingest endpoint], which forwards them to the Dynatrace backend: + +[source,yaml,indent=0,subs="verbatim",configprops,configblocks] +---- + management: + metrics: + export: + dynatrace: + api-version: "v2" +---- + +If no local OneAgent is running, the endpoint of the https://www.dynatrace.com/support/help/dynatrace-api/environment-api/metric-v2/post-ingest-metrics/[Metrics API v2] and an API token are required. +The https://www.dynatrace.com/support/help/dynatrace-api/basics/dynatrace-api-authentication/[API token] must have the "Ingest metrics" (`metrics.ingest`) permission set. +It is recommended to limit scope to only this one permission. +Please ensure that the endpoint URI contains the path (e.g. `/api/v2/metrics/ingest`). + +[source,yaml,indent=0,subs="verbatim",configprops,configblocks] +---- + management: + metrics: + export: + dynatrace: + api-version: "v2" + # uri: "https://{your-domain}/e/{your-environment-id}/api/v2/metrics/ingest" for managed deployments. + uri: "https://{your-environment-id}.live.dynatrace.com/api/v2/metrics/ingest" + api-token: "YOUR_TOKEN" # should be read from a secure source and not hard-coded. +---- + +When using the Dynatrace v2 API, the following optional features are available: + +* Metric key prefix: Sets a prefix that will be prepended to all exported metric keys. +* Enrich with Dynatrace metadata: If a OneAgent or Dynatrace operator is running, enrich metrics with additional metadata (e.g. about the host, process or pod). +* Default dimensions: Specify key-value pairs that are added to all exported metrics. +If tags with the same key are specified using Micrometer, they overwrite the default dimensions. + +[source,yaml,indent=0,subs="verbatim",configprops,configblocks] +---- + management: + metrics: + export: + dynatrace: + # specify token and uri or leave blank for OneAgent export + api-version: "v2" + metric-key-prefix: "your.key.prefix" + enrich-with-dynatrace-metadata: true + default-dimensions: + key1: "value1" + key2: "value2" +---- + +[[actuator.metrics.export.dynatrace.api-v1]] +===== API v1 (Legacy) + +The Dynatrace API v1 registry pushes metrics to the configured URI periodically using the https://www.dynatrace.com/support/help/dynatrace-api/environment-api/metric-v1/[Timeseries API v1]. +For backwards-compatibility with existing setups, `api-version` defaults to `"v1"` but can also be specified explicitly as such. To export metrics to {micrometer-registry-docs}/dynatrace[Dynatrace], your API token, device ID, and URI must be provided: +For the API v1, the base environment URI needs to be specified, without any path. +The API v1 endpoint path will be added automatically. [source,yaml,indent=0,subs="verbatim",configprops,configblocks] ---- @@ -156,12 +220,17 @@ To export metrics to {micrometer-registry-docs}/dynatrace[Dynatrace], your API t metrics: export: dynatrace: - api-token: "YOUR_TOKEN" device-id: "YOUR_DEVICE_ID" - uri: "YOUR_URI" + # uri: "https://{your-domain}/e/{your-environment-id}" on managed deployments. + uri: "https://{your-environment-id}.live.dynatrace.com" + api-token: "YOUR_TOKEN" # should be read from a secure property source ---- -You can also change the interval at which metrics are sent to Dynatrace: +[[actuator.metrics.export.dynatrace.version-independent-settings]] +===== Version-independent settings + +You can also change the interval at which metrics are sent to Dynatrace (works for both API versions). +The default export interval is `60s`. [source,yaml,indent=0,subs="verbatim",configprops,configblocks] ---- @@ -172,7 +241,7 @@ You can also change the interval at which metrics are sent to Dynatrace: step: "30s" ---- - +More information on how to set up the Dynatrace exporter for Micrometer can be found in {micrometer-registry-docs}/dynatrace[the Micrometer documentation]. [[actuator.metrics.export.elastic]] ==== Elastic From 84455f86fd5883eb096eea1791a2ed4a2b9bfdac Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Thu, 15 Jul 2021 12:41:52 +0100 Subject: [PATCH 2/4] Polish "Add properties for Dynatrace metrics API v2 ingest with Micrometer" --- .../export/dynatrace/DynatraceProperties.java | 187 ++++++++++-------- .../DynatracePropertiesConfigAdapter.java | 28 ++- ...ceMetricsExportAutoConfigurationTests.java | 24 ++- ...DynatracePropertiesConfigAdapterTests.java | 72 +++++-- .../dynatrace/DynatracePropertiesTests.java | 2 + .../src/docs/asciidoc/actuator/metrics.adoc | 46 ++--- 6 files changed, 218 insertions(+), 141 deletions(-) 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 index 297457d89a..31a3c076a5 100644 --- 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 @@ -18,10 +18,9 @@ package org.springframework.boot.actuate.autoconfigure.metrics.export.dynatrace; import java.util.Map; -import io.micrometer.dynatrace.DynatraceApiVersion; - import org.springframework.boot.actuate.autoconfigure.metrics.export.properties.StepRegistryProperties; import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.context.properties.DeprecatedConfigurationProperty; /** * {@link ConfigurationProperties @ConfigurationProperties} for configuring Dynatrace @@ -34,73 +33,21 @@ import org.springframework.boot.context.properties.ConfigurationProperties; @ConfigurationProperties(prefix = "management.metrics.export.dynatrace") public class DynatraceProperties extends StepRegistryProperties { - /** - * The Dynatrace metrics API version that metrics should be sent to. Defaults to v1. - * Required to define which API is used for export. - */ - private DynatraceApiVersion apiVersion = DynatraceApiVersion.V1; + private final V1 v1 = new V1(); + + private final V2 v2 = new V2(); /** * Dynatrace authentication token. - * - * API v1: required, API v2: optional */ private String apiToken; - /** - * ID of the custom device that is exporting metrics to Dynatrace. - * - * API v1: required, API v2: not applicable (ignored) - */ - private String deviceId; - - /** - * Technology type for exported metrics. Used to group metrics under a logical - * technology name in the Dynatrace UI. - * - * API v1: required, API v2: not applicable (ignored) - */ - private String technologyType = "java"; - /** * URI to ship metrics to. Should be used for SaaS, self managed instances or to * en-route through an internal proxy. - * - * API v1: required, API v2: optional */ private String uri; - /** - * Group for exported metrics. Used to specify custom device group name in the - * Dynatrace UI. - * - * API v1: required, API v2: not applicable (ignored) - */ - private String group; - - /** - * An optional prefix string that is added to all metrics exported. - * - * API v1: not applicable (ignored), API v2: optional - */ - private String metricKeyPrefix; - - /** - * An optional Boolean that allows enabling of the Dynatrace metadata export. On by - * default. - * - * API v1: not applicable (ignored), API v2: optional - */ - private Boolean enrichWithDynatraceMetadata = true; - - /** - * Optional default dimensions that are added to all metrics in the form of key-value - * pairs. These are overwritten by Micrometer tags if they use the same key. - * - * API v1: not applicable (ignored), API v2: optional - */ - private Map defaultDimensions; - public String getApiToken() { return this.apiToken; } @@ -109,20 +56,26 @@ public class DynatraceProperties extends StepRegistryProperties { this.apiToken = apiToken; } + @Deprecated + @DeprecatedConfigurationProperty(replacement = "management.metrics.export.dynatrace.v1.device-id") public String getDeviceId() { - return this.deviceId; + return this.v1.getDeviceId(); } + @Deprecated public void setDeviceId(String deviceId) { - this.deviceId = deviceId; + this.v1.setDeviceId(deviceId); } + @Deprecated + @DeprecatedConfigurationProperty(replacement = "management.metrics.export.dynatrace.v1.technology-type") public String getTechnologyType() { - return this.technologyType; + return this.v1.getTechnologyType(); } + @Deprecated public void setTechnologyType(String technologyType) { - this.technologyType = technologyType; + this.v1.setTechnologyType(technologyType); } public String getUri() { @@ -133,44 +86,112 @@ public class DynatraceProperties extends StepRegistryProperties { this.uri = uri; } + @Deprecated + @DeprecatedConfigurationProperty(replacement = "management.metrics.export.dynatrace.v1.group") public String getGroup() { - return this.group; + return this.v1.getGroup(); } + @Deprecated public void setGroup(String group) { - this.group = group; + this.v1.setGroup(group); } - public String getMetricKeyPrefix() { - return this.metricKeyPrefix; + public V1 getV1() { + return this.v1; } - public void setMetricKeyPrefix(String metricKeyPrefix) { - this.metricKeyPrefix = metricKeyPrefix; + public V2 getV2() { + return this.v2; } - public Boolean getEnrichWithDynatraceMetadata() { - return this.enrichWithDynatraceMetadata; - } + public static class V1 { - public void setEnrichWithDynatraceMetadata(Boolean enrichWithDynatraceMetadata) { - this.enrichWithDynatraceMetadata = enrichWithDynatraceMetadata; - } + /** + * ID of the custom device that is exporting metrics to Dynatrace. + */ + private String deviceId; - public Map getDefaultDimensions() { - return this.defaultDimensions; - } + /** + * Group for exported metrics. Used to specify custom device group name in the + * Dynatrace UI. + */ + private String group; - public void setDefaultDimensions(Map defaultDimensions) { - this.defaultDimensions = defaultDimensions; - } + /** + * Technology type for exported metrics. Used to group metrics under a logical + * technology name in the Dynatrace UI. + */ + private String technologyType = "java"; + + public String getDeviceId() { + return this.deviceId; + } + + public void setDeviceId(String deviceId) { + this.deviceId = deviceId; + } + + public String getGroup() { + return this.group; + } + + public void setGroup(String group) { + this.group = group; + } + + public String getTechnologyType() { + return this.technologyType; + } + + public void setTechnologyType(String technologyType) { + this.technologyType = technologyType; + } - public DynatraceApiVersion getApiVersion() { - return this.apiVersion; } - public void setApiVersion(DynatraceApiVersion apiVersion) { - this.apiVersion = apiVersion; + public static class V2 { + + /** + * Default dimensions that are added to all metrics in the form of key-value + * pairs. These are overwritten by Micrometer tags if they use the same key. + */ + private Map defaultDimensions; + + /** + * Whether to enable Dynatrace metadata export. + */ + private boolean enrichWithDynatraceMetadata = true; + + /** + * Prefix string that is added to all exported metrics. + */ + private String metricKeyPrefix; + + public Map getDefaultDimensions() { + return this.defaultDimensions; + } + + public void setDefaultDimensions(Map defaultDimensions) { + this.defaultDimensions = defaultDimensions; + } + + public boolean isEnrichWithDynatraceMetadata() { + return this.enrichWithDynatraceMetadata; + } + + public void setEnrichWithDynatraceMetadata(Boolean enrichWithDynatraceMetadata) { + this.enrichWithDynatraceMetadata = enrichWithDynatraceMetadata; + } + + public String getMetricKeyPrefix() { + return this.metricKeyPrefix; + } + + public void setMetricKeyPrefix(String metricKeyPrefix) { + this.metricKeyPrefix = metricKeyPrefix; + } + } } 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 index 7e232ffe0e..7df441b64e 100644 --- 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 @@ -17,10 +17,13 @@ package org.springframework.boot.actuate.autoconfigure.metrics.export.dynatrace; import java.util.Map; +import java.util.function.Function; import io.micrometer.dynatrace.DynatraceApiVersion; import io.micrometer.dynatrace.DynatraceConfig; +import org.springframework.boot.actuate.autoconfigure.metrics.export.dynatrace.DynatraceProperties.V1; +import org.springframework.boot.actuate.autoconfigure.metrics.export.dynatrace.DynatraceProperties.V2; import org.springframework.boot.actuate.autoconfigure.metrics.export.properties.StepRegistryPropertiesConfigAdapter; /** @@ -48,12 +51,12 @@ class DynatracePropertiesConfigAdapter extends StepRegistryPropertiesConfigAdapt @Override public String deviceId() { - return get(DynatraceProperties::getDeviceId, DynatraceConfig.super::deviceId); + return get(v1(V1::getDeviceId), DynatraceConfig.super::deviceId); } @Override public String technologyType() { - return get(DynatraceProperties::getTechnologyType, DynatraceConfig.super::technologyType); + return get(v1(V1::getTechnologyType), DynatraceConfig.super::technologyType); } @Override @@ -63,27 +66,36 @@ class DynatracePropertiesConfigAdapter extends StepRegistryPropertiesConfigAdapt @Override public String group() { - return get(DynatraceProperties::getGroup, DynatraceConfig.super::group); + return get(v1(V1::getGroup), DynatraceConfig.super::group); } @Override public DynatraceApiVersion apiVersion() { - return get(DynatraceProperties::getApiVersion, DynatraceConfig.super::apiVersion); + return get((properties) -> (properties.getV1().getDeviceId() != null) ? DynatraceApiVersion.V1 + : DynatraceApiVersion.V2, DynatraceConfig.super::apiVersion); } @Override public String metricKeyPrefix() { - return get(DynatraceProperties::getMetricKeyPrefix, DynatraceConfig.super::metricKeyPrefix); + return get(v2(V2::getMetricKeyPrefix), DynatraceConfig.super::metricKeyPrefix); } @Override public Map defaultDimensions() { - return get(DynatraceProperties::getDefaultDimensions, DynatraceConfig.super::defaultDimensions); + return get(v2(V2::getDefaultDimensions), DynatraceConfig.super::defaultDimensions); } @Override public boolean enrichWithDynatraceMetadata() { - return get(DynatraceProperties::getEnrichWithDynatraceMetadata, - DynatraceConfig.super::enrichWithDynatraceMetadata); + return get(v2(V2::isEnrichWithDynatraceMetadata), DynatraceConfig.super::enrichWithDynatraceMetadata); } + + private Function v1(Function getter) { + return (properties) -> getter.apply(properties.getV1()); + } + + private Function v2(Function getter) { + return (properties) -> getter.apply(properties.getV2()); + } + } 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 index 6525488881..23e26cc3d4 100644 --- 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 @@ -48,14 +48,15 @@ class DynatraceMetricsExportAutoConfigurationTests { } @Test - void failsWithoutAUri() { + void failsWithADeviceIdWithoutAUri() { this.contextRunner.withUserConfiguration(BaseConfiguration.class) + .withPropertyValues("management.metrics.export.dynatrace.device-id:dev-1") .run((context) -> assertThat(context).hasFailed()); } @Test void autoConfiguresConfigAndMeterRegistry() { - this.contextRunner.withUserConfiguration(BaseConfiguration.class).with(mandatoryProperties()) + this.contextRunner.withUserConfiguration(BaseConfiguration.class).with(v1MandatoryProperties()) .run((context) -> assertThat(context).hasSingleBean(DynatraceMeterRegistry.class) .hasSingleBean(DynatraceConfig.class)); } @@ -85,14 +86,25 @@ class DynatraceMetricsExportAutoConfigurationTests { @Test void allowsCustomRegistryToBeUsed() { - this.contextRunner.withUserConfiguration(CustomRegistryConfiguration.class).with(mandatoryProperties()) + this.contextRunner.withUserConfiguration(CustomRegistryConfiguration.class).with(v1MandatoryProperties()) .run((context) -> assertThat(context).hasSingleBean(DynatraceMeterRegistry.class) .hasBean("customRegistry").hasSingleBean(DynatraceConfig.class)); } @Test - void stopsMeterRegistryWhenContextIsClosed() { - this.contextRunner.withUserConfiguration(BaseConfiguration.class).with(mandatoryProperties()).run((context) -> { + void stopsMeterRegistryForV1ApiWhenContextIsClosed() { + this.contextRunner.withUserConfiguration(BaseConfiguration.class).with(v1MandatoryProperties()) + .run((context) -> { + DynatraceMeterRegistry registry = context.getBean(DynatraceMeterRegistry.class); + assertThat(registry.isClosed()).isFalse(); + context.close(); + assertThat(registry.isClosed()).isTrue(); + }); + } + + @Test + void stopsMeterRegistryForV2ApiWhenContextIsClosed() { + this.contextRunner.withUserConfiguration(BaseConfiguration.class).run((context) -> { DynatraceMeterRegistry registry = context.getBean(DynatraceMeterRegistry.class); assertThat(registry.isClosed()).isFalse(); context.close(); @@ -100,7 +112,7 @@ class DynatraceMetricsExportAutoConfigurationTests { }); } - private Function mandatoryProperties() { + private Function v1MandatoryProperties() { return (runner) -> runner.withPropertyValues( "management.metrics.export.dynatrace.uri=https://dynatrace.example.com", "management.metrics.export.dynatrace.api-token=abcde", 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 index 74aaa5e454..f6c72c60c8 100644 --- 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 @@ -46,6 +46,7 @@ class DynatracePropertiesConfigAdapterTests { } @Test + @Deprecated void whenPropertiesDeviceIdIsSetAdapterDeviceIdReturnsIt() { DynatraceProperties properties = new DynatraceProperties(); properties.setDeviceId("dev-1"); @@ -53,6 +54,15 @@ class DynatracePropertiesConfigAdapterTests { } @Test + @Deprecated + void whenPropertiesV1DeviceIdIsSetAdapterDeviceIdReturnsIt() { + DynatraceProperties properties = new DynatraceProperties(); + properties.getV1().setDeviceId("dev-1"); + assertThat(new DynatracePropertiesConfigAdapter(properties).deviceId()).isEqualTo("dev-1"); + } + + @Test + @Deprecated void whenPropertiesTechnologyTypeIsSetAdapterTechnologyTypeReturnsIt() { DynatraceProperties properties = new DynatraceProperties(); properties.setTechnologyType("tech-1"); @@ -60,6 +70,14 @@ class DynatracePropertiesConfigAdapterTests { } @Test + void whenPropertiesV1TechnologyTypeIsSetAdapterTechnologyTypeReturnsIt() { + DynatraceProperties properties = new DynatraceProperties(); + properties.getV1().setTechnologyType("tech-1"); + assertThat(new DynatracePropertiesConfigAdapter(properties).technologyType()).isEqualTo("tech-1"); + } + + @Test + @Deprecated void whenPropertiesGroupIsSetAdapterGroupReturnsIt() { DynatraceProperties properties = new DynatraceProperties(); properties.setGroup("group-1"); @@ -67,53 +85,73 @@ class DynatracePropertiesConfigAdapterTests { } @Test - void whenPropertiesApiVersionIsSetAdapterGroupReturnsIt() { + void whenPropertiesV1GroupIsSetAdapterGroupReturnsIt() { DynatraceProperties properties = new DynatraceProperties(); - properties.setApiVersion(DynatraceApiVersion.V1); + properties.getV1().setGroup("group-1"); + assertThat(new DynatracePropertiesConfigAdapter(properties).group()).isEqualTo("group-1"); + } + + @Test + @SuppressWarnings("deprecation") + void whenDeviceIdIsSetThenAdapterApiVersionIsV1() { + DynatraceProperties properties = new DynatraceProperties(); + properties.setDeviceId("dev-1"); + assertThat(new DynatracePropertiesConfigAdapter(properties).apiVersion()).isSameAs(DynatraceApiVersion.V1); + } + + @Test + void whenV1DeviceIdIsSetThenAdapterApiVersionIsV1() { + DynatraceProperties properties = new DynatraceProperties(); + properties.getV1().setDeviceId("dev-1"); assertThat(new DynatracePropertiesConfigAdapter(properties).apiVersion()).isSameAs(DynatraceApiVersion.V1); } + @Test + void whenDeviceIdIsNotSetThenAdapterApiVersionIsV2() { + DynatraceProperties properties = new DynatraceProperties(); + assertThat(new DynatracePropertiesConfigAdapter(properties).apiVersion()).isSameAs(DynatraceApiVersion.V2); + } + @Test void whenPropertiesMetricKeyPrefixIsSetAdapterGroupReturnsIt() { DynatraceProperties properties = new DynatraceProperties(); - properties.setMetricKeyPrefix("my.prefix"); + properties.getV2().setMetricKeyPrefix("my.prefix"); assertThat(new DynatracePropertiesConfigAdapter(properties).metricKeyPrefix()).isEqualTo("my.prefix"); } @Test void whenPropertiesEnrichWithOneAgentMetadataIsSetAdapterGroupReturnsIt() { DynatraceProperties properties = new DynatraceProperties(); - properties.setEnrichWithDynatraceMetadata(true); + properties.getV2().setEnrichWithDynatraceMetadata(true); assertThat(new DynatracePropertiesConfigAdapter(properties).enrichWithDynatraceMetadata()).isTrue(); } @Test void whenPropertiesDefaultDimensionsIsSetAdapterGroupReturnsIt() { DynatraceProperties properties = new DynatraceProperties(); - HashMap defaultDimensions = new HashMap() { - { - put("dim1", "value1"); - put("dim2", "value2"); - } - }; - - properties.setDefaultDimensions(defaultDimensions); + HashMap defaultDimensions = new HashMap<>(); + defaultDimensions.put("dim1", "value1"); + defaultDimensions.put("dim2", "value2"); + properties.getV2().setDefaultDimensions(defaultDimensions); assertThat(new DynatracePropertiesConfigAdapter(properties).defaultDimensions()) .containsExactlyEntriesOf(defaultDimensions); } @Test + @SuppressWarnings("deprecation") void defaultValues() { DynatraceProperties properties = new DynatraceProperties(); assertThat(properties.getApiToken()).isNull(); + assertThat(properties.getUri()).isNull(); + assertThat(properties.getV1().getDeviceId()).isNull(); + assertThat(properties.getV1().getTechnologyType()).isEqualTo("java"); + assertThat(properties.getV1().getGroup()).isNull(); + assertThat(properties.getV2().getMetricKeyPrefix()).isNull(); + assertThat(properties.getV2().isEnrichWithDynatraceMetadata()).isTrue(); + assertThat(properties.getV2().getDefaultDimensions()).isNull(); assertThat(properties.getDeviceId()).isNull(); assertThat(properties.getTechnologyType()).isEqualTo("java"); - assertThat(properties.getUri()).isNull(); assertThat(properties.getGroup()).isNull(); - assertThat(properties.getApiVersion()).isSameAs(DynatraceApiVersion.V1); - assertThat(properties.getMetricKeyPrefix()).isNull(); - assertThat(properties.getEnrichWithDynatraceMetadata()).isTrue(); - assertThat(properties.getDefaultDimensions()).isNull(); } } 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 index 51a3708bb0..177e607ff3 100644 --- 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 @@ -30,12 +30,14 @@ import static org.assertj.core.api.Assertions.assertThat; */ class DynatracePropertiesTests extends StepRegistryPropertiesTests { + @SuppressWarnings("deprecation") @Test void defaultValuesAreConsistent() { DynatraceProperties properties = new DynatraceProperties(); DynatraceConfig config = (key) -> null; assertStepRegistryDefaultValues(properties, config); assertThat(properties.getTechnologyType()).isEqualTo(config.technologyType()); + assertThat(properties.getV1().getTechnologyType()).isEqualTo(config.technologyType()); } } diff --git a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/actuator/metrics.adoc b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/actuator/metrics.adoc index 6187617337..215194c0df 100644 --- a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/actuator/metrics.adoc +++ b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/actuator/metrics.adoc @@ -150,23 +150,15 @@ You can also change the interval at which metrics are sent to Datadog: Dynatrace offers two metrics ingest APIs, both of which are implemented for {micrometer-registry-docs}/dynatrace[Micrometer]: -[[actuator.metrics.export.dynatrace.api-v2]] -===== API v2 +[[actuator.metrics.export.dynatrace.v2-api]] +===== V2 API -The API v2 can be used in two ways: +The V2 API can be used in two ways: -If a local OneAgent is running on the host, it is enough to set the API version to v2 and metrics will be automatically exported to the https://www.dynatrace.com/support/help/how-to-use-dynatrace/metrics/metric-ingestion/ingestion-methods/local-api/[local OneAgent ingest endpoint], which forwards them to the Dynatrace backend: +If a local OneAgent is running on the host, metrics will be automatically exported to the https://www.dynatrace.com/support/help/how-to-use-dynatrace/metrics/metric-ingestion/ingestion-methods/local-api/[local OneAgent ingest endpoint], which forwards them to the Dynatrace backend. -[source,yaml,indent=0,subs="verbatim",configprops,configblocks] ----- - management: - metrics: - export: - dynatrace: - api-version: "v2" ----- -If no local OneAgent is running, the endpoint of the https://www.dynatrace.com/support/help/dynatrace-api/environment-api/metric-v2/post-ingest-metrics/[Metrics API v2] and an API token are required. +If no local OneAgent is running, the endpoint of the https://www.dynatrace.com/support/help/dynatrace-api/environment-api/metric-v2/post-ingest-metrics/[Metrics v2 API] and an API token are required. The https://www.dynatrace.com/support/help/dynatrace-api/basics/dynatrace-api-authentication/[API token] must have the "Ingest metrics" (`metrics.ingest`) permission set. It is recommended to limit scope to only this one permission. Please ensure that the endpoint URI contains the path (e.g. `/api/v2/metrics/ingest`). @@ -177,7 +169,6 @@ Please ensure that the endpoint URI contains the path (e.g. `/api/v2/metrics/ing metrics: export: dynatrace: - api-version: "v2" # uri: "https://{your-domain}/e/{your-environment-id}/api/v2/metrics/ingest" for managed deployments. uri: "https://{your-environment-id}.live.dynatrace.com/api/v2/metrics/ingest" api-token: "YOUR_TOKEN" # should be read from a secure source and not hard-coded. @@ -196,23 +187,21 @@ If tags with the same key are specified using Micrometer, they overwrite the def metrics: export: dynatrace: - # specify token and uri or leave blank for OneAgent export - api-version: "v2" - metric-key-prefix: "your.key.prefix" - enrich-with-dynatrace-metadata: true - default-dimensions: - key1: "value1" - key2: "value2" + v2: + # specify token and uri or leave blank for OneAgent export + metric-key-prefix: "your.key.prefix" + enrich-with-dynatrace-metadata: true + default-dimensions: + key1: "value1" + key2: "value2" ---- -[[actuator.metrics.export.dynatrace.api-v1]] -===== API v1 (Legacy) +[[actuator.metrics.export.dynatrace.v1-api]] +===== v1 API (Legacy) -The Dynatrace API v1 registry pushes metrics to the configured URI periodically using the https://www.dynatrace.com/support/help/dynatrace-api/environment-api/metric-v1/[Timeseries API v1]. +The Dynatrace v1 API registry pushes metrics to the configured URI periodically using the https://www.dynatrace.com/support/help/dynatrace-api/environment-api/metric-v1/[Timeseries v1 API]. For backwards-compatibility with existing setups, `api-version` defaults to `"v1"` but can also be specified explicitly as such. To export metrics to {micrometer-registry-docs}/dynatrace[Dynatrace], your API token, device ID, and URI must be provided: -For the API v1, the base environment URI needs to be specified, without any path. -The API v1 endpoint path will be added automatically. [source,yaml,indent=0,subs="verbatim",configprops,configblocks] ---- @@ -220,12 +209,15 @@ The API v1 endpoint path will be added automatically. metrics: export: dynatrace: - device-id: "YOUR_DEVICE_ID" # uri: "https://{your-domain}/e/{your-environment-id}" on managed deployments. uri: "https://{your-environment-id}.live.dynatrace.com" api-token: "YOUR_TOKEN" # should be read from a secure property source + v1: + device-id: "YOUR_DEVICE_ID" ---- +For the v1 API, the base environment URI must be specified without a path as the v1 endpoint path will be added automatically. + [[actuator.metrics.export.dynatrace.version-independent-settings]] ===== Version-independent settings From d0cd3ab1d310af508daf80927fcea945daec7334 Mon Sep 17 00:00:00 2001 From: Georg Pirklbauer Date: Fri, 16 Jul 2021 15:24:03 +0200 Subject: [PATCH 3/4] Refine documentation See gh-26258 --- .../src/docs/asciidoc/actuator/metrics.adoc | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/actuator/metrics.adoc b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/actuator/metrics.adoc index 215194c0df..ba51ac27a8 100644 --- a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/actuator/metrics.adoc +++ b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/actuator/metrics.adoc @@ -148,15 +148,20 @@ You can also change the interval at which metrics are sent to Datadog: [[actuator.metrics.export.dynatrace]] ==== Dynatrace -Dynatrace offers two metrics ingest APIs, both of which are implemented for {micrometer-registry-docs}/dynatrace[Micrometer]: +Dynatrace offers two metrics ingest APIs, both of which are implemented for {micrometer-registry-docs}/dynatrace[Micrometer]. +Config properties in the `v1` namespace only apply when exporting to the https://www.dynatrace.com/support/help/dynatrace-api/environment-api/metric-v1/[Timeseries v1 API]. +Config properties in the `v2` namespace only apply when exporting to the https://www.dynatrace.com/support/help/dynatrace-api/environment-api/metric-v2/post-ingest-metrics/[Metrics v2 API]. +Please note that this integration can only export to either the `v1` or `v2` version of the API at the same time. +If the `device-id` (required for v1, but not used in v2) is set in the `v1` namespace, metrics will be exported to the `v1` endpoint. Otherwise, `v2` is assumed. [[actuator.metrics.export.dynatrace.v2-api]] -===== V2 API +===== v2 API -The V2 API can be used in two ways: +The v2 API can be used in two ways: If a local OneAgent is running on the host, metrics will be automatically exported to the https://www.dynatrace.com/support/help/how-to-use-dynatrace/metrics/metric-ingestion/ingestion-methods/local-api/[local OneAgent ingest endpoint], which forwards them to the Dynatrace backend. - +This is the default behaviour and requires no special set up. +Simply include a dependency to `'io.micrometer:micrometer-registry-dynatrace'` in your project, and metrics will be exported to the local OneAgent endpoint. If no local OneAgent is running, the endpoint of the https://www.dynatrace.com/support/help/dynatrace-api/environment-api/metric-v2/post-ingest-metrics/[Metrics v2 API] and an API token are required. The https://www.dynatrace.com/support/help/dynatrace-api/basics/dynatrace-api-authentication/[API token] must have the "Ingest metrics" (`metrics.ingest`) permission set. @@ -181,14 +186,15 @@ When using the Dynatrace v2 API, the following optional features are available: * Default dimensions: Specify key-value pairs that are added to all exported metrics. If tags with the same key are specified using Micrometer, they overwrite the default dimensions. + [source,yaml,indent=0,subs="verbatim",configprops,configblocks] ---- management: metrics: export: dynatrace: + # specify token and uri or leave blank for OneAgent export v2: - # specify token and uri or leave blank for OneAgent export metric-key-prefix: "your.key.prefix" enrich-with-dynatrace-metadata: true default-dimensions: @@ -200,7 +206,7 @@ If tags with the same key are specified using Micrometer, they overwrite the def ===== v1 API (Legacy) The Dynatrace v1 API registry pushes metrics to the configured URI periodically using the https://www.dynatrace.com/support/help/dynatrace-api/environment-api/metric-v1/[Timeseries v1 API]. -For backwards-compatibility with existing setups, `api-version` defaults to `"v1"` but can also be specified explicitly as such. +For backwards-compatibility with existing setups, when `device-id` is set (required for v1, but not used in v2), metrics will be exported to the Timeseries v1 endpoint. To export metrics to {micrometer-registry-docs}/dynatrace[Dynatrace], your API token, device ID, and URI must be provided: [source,yaml,indent=0,subs="verbatim",configprops,configblocks] @@ -221,7 +227,7 @@ For the v1 API, the base environment URI must be specified without a path as the [[actuator.metrics.export.dynatrace.version-independent-settings]] ===== Version-independent settings -You can also change the interval at which metrics are sent to Dynatrace (works for both API versions). +In addition to the API endpoint and token, you can also change the interval at which metrics are sent to Dynatrace. The default export interval is `60s`. [source,yaml,indent=0,subs="verbatim",configprops,configblocks] @@ -249,8 +255,6 @@ The location of the Elastic server to use can be provided using the following pr host: "https://elastic.example.com:8086" ---- - - [[actuator.metrics.export.ganglia]] ==== Ganglia By default, metrics are exported to {micrometer-registry-docs}/ganglia[Ganglia] running on your local machine. From 21b3202ab22c004b4fcbb3ce29ecb41156b0742e Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Fri, 16 Jul 2021 17:17:57 +0100 Subject: [PATCH 4/4] Polish "Refine documentation" See gh-26258 --- .../src/docs/asciidoc/actuator/metrics.adoc | 47 ++++++++++--------- .../src/docs/asciidoc/attributes.adoc | 1 + 2 files changed, 27 insertions(+), 21 deletions(-) diff --git a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/actuator/metrics.adoc b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/actuator/metrics.adoc index ba51ac27a8..c46ce82bd4 100644 --- a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/actuator/metrics.adoc +++ b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/actuator/metrics.adoc @@ -147,25 +147,26 @@ You can also change the interval at which metrics are sent to Datadog: [[actuator.metrics.export.dynatrace]] ==== Dynatrace - Dynatrace offers two metrics ingest APIs, both of which are implemented for {micrometer-registry-docs}/dynatrace[Micrometer]. -Config properties in the `v1` namespace only apply when exporting to the https://www.dynatrace.com/support/help/dynatrace-api/environment-api/metric-v1/[Timeseries v1 API]. -Config properties in the `v2` namespace only apply when exporting to the https://www.dynatrace.com/support/help/dynatrace-api/environment-api/metric-v2/post-ingest-metrics/[Metrics v2 API]. -Please note that this integration can only export to either the `v1` or `v2` version of the API at the same time. -If the `device-id` (required for v1, but not used in v2) is set in the `v1` namespace, metrics will be exported to the `v1` endpoint. Otherwise, `v2` is assumed. +Config properties in the `v1` namespace only apply when exporting to the {dynatrace-help}/dynatrace-api/environment-api/metric-v1/[Timeseries v1 API]. +Config properties in the `v2` namespace only apply when exporting to the {dynatrace-help}/dynatrace-api/environment-api/metric-v2/post-ingest-metrics/[Metrics v2 API]. +Please note that this integration can only export to either the `v1` or `v2` version of the API at a time. +If the `device-id` (required for v1, but not used in v2) is set in the `v1` namespace, metrics will be exported to the `v1` endpoint. +Otherwise, `v2` is assumed. + + [[actuator.metrics.export.dynatrace.v2-api]] ===== v2 API +The v2 API can be used in two ways. -The v2 API can be used in two ways: +If a local OneAgent is running on the host, metrics will be automatically exported to the {dynatrace-help}/how-to-use-dynatrace/metrics/metric-ingestion/ingestion-methods/local-api/[local OneAgent ingest endpoint]. +The ingest endpoint forwards the metrics to the Dynatrace backend. +This is the default behaviour and requires no special setup beyond a dependency on `io.micrometer:micrometer-registry-dynatrace`. -If a local OneAgent is running on the host, metrics will be automatically exported to the https://www.dynatrace.com/support/help/how-to-use-dynatrace/metrics/metric-ingestion/ingestion-methods/local-api/[local OneAgent ingest endpoint], which forwards them to the Dynatrace backend. -This is the default behaviour and requires no special set up. -Simply include a dependency to `'io.micrometer:micrometer-registry-dynatrace'` in your project, and metrics will be exported to the local OneAgent endpoint. - -If no local OneAgent is running, the endpoint of the https://www.dynatrace.com/support/help/dynatrace-api/environment-api/metric-v2/post-ingest-metrics/[Metrics v2 API] and an API token are required. -The https://www.dynatrace.com/support/help/dynatrace-api/basics/dynatrace-api-authentication/[API token] must have the "Ingest metrics" (`metrics.ingest`) permission set. -It is recommended to limit scope to only this one permission. +If no local OneAgent is running, the endpoint of the {dynatrace-help}/dynatrace-api/environment-api/metric-v2/post-ingest-metrics/[Metrics v2 API] and an API token are required. +The {dynatrace-help}/dynatrace-api/basics/dynatrace-api-authentication/[API token] must have the "Ingest metrics" (`metrics.ingest`) permission set. +It is recommended to limit the scope of the token to this one permission. Please ensure that the endpoint URI contains the path (e.g. `/api/v2/metrics/ingest`). [source,yaml,indent=0,subs="verbatim",configprops,configblocks] @@ -181,10 +182,10 @@ Please ensure that the endpoint URI contains the path (e.g. `/api/v2/metrics/ing When using the Dynatrace v2 API, the following optional features are available: -* Metric key prefix: Sets a prefix that will be prepended to all exported metric keys. -* Enrich with Dynatrace metadata: If a OneAgent or Dynatrace operator is running, enrich metrics with additional metadata (e.g. about the host, process or pod). -* Default dimensions: Specify key-value pairs that are added to all exported metrics. -If tags with the same key are specified using Micrometer, they overwrite the default dimensions. +* Metric key prefix: sets a prefix that will be prepended to all exported metric keys. +* Enrich with Dynatrace metadata: if a OneAgent or Dynatrace operator is running, enrich metrics with additional metadata (e.g. about the host, process or pod). +* Default dimensions: specify key-value pairs that are added to all exported metrics. + If tags with the same key are specified using Micrometer, they overwrite the default dimensions. [source,yaml,indent=0,subs="verbatim",configprops,configblocks] @@ -202,10 +203,11 @@ If tags with the same key are specified using Micrometer, they overwrite the def key2: "value2" ---- + + [[actuator.metrics.export.dynatrace.v1-api]] ===== v1 API (Legacy) - -The Dynatrace v1 API registry pushes metrics to the configured URI periodically using the https://www.dynatrace.com/support/help/dynatrace-api/environment-api/metric-v1/[Timeseries v1 API]. +The Dynatrace v1 API metrics registry pushes metrics to the configured URI periodically using the {dynatrace-help}/dynatrace-api/environment-api/metric-v1/[Timeseries v1 API]. For backwards-compatibility with existing setups, when `device-id` is set (required for v1, but not used in v2), metrics will be exported to the Timeseries v1 endpoint. To export metrics to {micrometer-registry-docs}/dynatrace[Dynatrace], your API token, device ID, and URI must be provided: @@ -224,9 +226,10 @@ To export metrics to {micrometer-registry-docs}/dynatrace[Dynatrace], your API t For the v1 API, the base environment URI must be specified without a path as the v1 endpoint path will be added automatically. -[[actuator.metrics.export.dynatrace.version-independent-settings]] -===== Version-independent settings + +[[actuator.metrics.export.dynatrace.version-independent-settings]] +===== Version-independent Settings In addition to the API endpoint and token, you can also change the interval at which metrics are sent to Dynatrace. The default export interval is `60s`. @@ -241,6 +244,8 @@ The default export interval is `60s`. More information on how to set up the Dynatrace exporter for Micrometer can be found in {micrometer-registry-docs}/dynatrace[the Micrometer documentation]. + + [[actuator.metrics.export.elastic]] ==== Elastic By default, metrics are exported to {micrometer-registry-docs}/elastic[Elastic] running on your local machine. diff --git a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/attributes.adoc b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/attributes.adoc index 941982411e..8e433bfb4d 100644 --- a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/attributes.adoc +++ b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/attributes.adoc @@ -93,6 +93,7 @@ :spring-webservices-docs: https://docs.spring.io/spring-ws/docs/{spring-webservices-version}/reference/html/ :ant-docs: https://ant.apache.org/manual :dependency-management-plugin-code: https://github.com/spring-gradle-plugins/dependency-management-plugin +:dynatrace-help: https://www.dynatrace.com/support/help :embedded-mongo-code: https://github.com/flapdoodle-oss/de.flapdoodle.embed.mongo/blob/de.flapdoodle.embed.mongo-{embedded-mongo-version} :gradle-docs: https://docs.gradle.org/current/userguide :hibernate-docs: https://docs.jboss.org/hibernate/orm/5.4/userguide/html_single/Hibernate_User_Guide.html