Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -16,47 +16,38 @@

package org.springframework.boot.actuate.autoconfigure.metrics.export.dynatrace;

import java.util.Map;

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
* metrics export.
*
* @author Andy Wilkinson
* @author Georg Pirklbauer
* @since 2.1.0
*/
@ConfigurationProperties(prefix = "management.metrics.export.dynatrace")
public class DynatraceProperties extends StepRegistryProperties {

/**
* Dynatrace authentication token.
*/
private String apiToken;
private final V1 v1 = new V1();

/**
* ID of the custom device that is exporting metrics to Dynatrace.
*/
private String deviceId;
private final V2 v2 = new V2();

/**
* Technology type for exported metrics. Used to group metrics under a logical
* technology name in the Dynatrace UI.
* Dynatrace authentication token.
*/
private String technologyType = "java";
private String apiToken;

/**
* URI to ship metrics to. Should be used for SaaS, self managed instances or to
* en-route through an internal proxy.
*/
private String uri;

/**
* Group for exported metrics. Used to specify custom device group name in the
* Dynatrace UI.
*/
private String group;

public String getApiToken() {
return this.apiToken;
}
Expand All @@ -65,20 +56,26 @@ public void setApiToken(String apiToken) {
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() {
Expand All @@ -89,12 +86,112 @@ public void setUri(String uri) {
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 V1 getV1() {
return this.v1;
}

public V2 getV2() {
return this.v2;
}

public static class V1 {

/**
* ID of the custom device that is exporting metrics to Dynatrace.
*/
private String deviceId;

/**
* Group for exported metrics. Used to specify custom device group name in the
* Dynatrace UI.
*/
private String group;

/**
* 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 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<String, String> 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<String, String> getDefaultDimensions() {
return this.defaultDimensions;
}

public void setDefaultDimensions(Map<String, String> 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;
}

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,21 @@

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;

/**
* Adapter to convert {@link DynatraceProperties} to a {@link DynatraceConfig}.
*
* @author Andy Wilkinson
* @author Georg Pirklbauer
*/
class DynatracePropertiesConfigAdapter extends StepRegistryPropertiesConfigAdapter<DynatraceProperties>
implements DynatraceConfig {
Expand All @@ -44,12 +51,12 @@ public String apiToken() {

@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
Expand All @@ -59,7 +66,36 @@ public String uri() {

@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((properties) -> (properties.getV1().getDeviceId() != null) ? DynatraceApiVersion.V1
: DynatraceApiVersion.V2, DynatraceConfig.super::apiVersion);
}

@Override
public String metricKeyPrefix() {
return get(v2(V2::getMetricKeyPrefix), DynatraceConfig.super::metricKeyPrefix);
}

@Override
public Map<String, String> defaultDimensions() {
return get(v2(V2::getDefaultDimensions), DynatraceConfig.super::defaultDimensions);
}

@Override
public boolean enrichWithDynatraceMetadata() {
return get(v2(V2::isEnrichWithDynatraceMetadata), DynatraceConfig.super::enrichWithDynatraceMetadata);
}

private <V> Function<DynatraceProperties, V> v1(Function<V1, V> getter) {
return (properties) -> getter.apply(properties.getV1());
}

private <V> Function<DynatraceProperties, V> v2(Function<V2, V> getter) {
return (properties) -> getter.apply(properties.getV2());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,15 @@ void backsOffWithoutAClock() {
}

@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));
}
Expand Down Expand Up @@ -85,22 +86,33 @@ void allowsCustomConfigToBeUsed() {

@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();
assertThat(registry.isClosed()).isTrue();
});
}

private Function<ApplicationContextRunner, ApplicationContextRunner> mandatoryProperties() {
private Function<ApplicationContextRunner, ApplicationContextRunner> v1MandatoryProperties() {
return (runner) -> runner.withPropertyValues(
"management.metrics.export.dynatrace.uri=https://dynatrace.example.com",
"management.metrics.export.dynatrace.api-token=abcde",
Expand Down
Loading