Fix PropertiesConfigAdapter delegation logic

This change replaces fallback logic in PropertiesConfigAdapter and its
descendants such that instead of falling back to default "empty" config
it delegates to superinterface default implementation of the same class.

This allows default implementation to call back to other properties,
like DatadogConfig.uri() does.

See gh-11135
This commit is contained in:
Nikolay Rybak 2017-11-24 12:23:37 +02:00 committed by Stephane Nicoll
parent b3c5a050ad
commit 9163d65b0e
11 changed files with 146 additions and 103 deletions

View File

@ -17,6 +17,7 @@
package org.springframework.boot.actuate.autoconfigure.metrics.export;
import java.util.function.Function;
import java.util.function.Supplier;
import org.springframework.util.Assert;
@ -24,38 +25,32 @@ import org.springframework.util.Assert;
* Base class for properties to config adapters.
*
* @param <T> The properties type
* @param <C> The config type
* @author Phillip Webb
* @since 2.0.0
*/
public class PropertiesConfigAdapter<T, C> {
public class PropertiesConfigAdapter<T> {
private T properties;
private C defaults;
/**
* Create a new {@link PropertiesConfigAdapter} instance.
* @param properties the source properties
* @param defaults a config implementation providing default values
*/
public PropertiesConfigAdapter(T properties, C defaults) {
public PropertiesConfigAdapter(T properties) {
Assert.notNull(properties, "Properties must not be null");
Assert.notNull(defaults, "Defaults must not be null");
this.properties = properties;
this.defaults = defaults;
}
/**
* Get the value from the properties or use a fallback from the {@code defaults}.
* @param getter the getter for the properties
* @param fallback the fallback method from the {@code defaults}
* @param fallback the fallback method, usually super interface method reference
* @param <V> the value type
* @return the property or fallback value
*/
protected final <V> V get(Function<T, V> getter, Function<C, V> fallback) {
protected final <V> V get(Function<T, V> getter, Supplier<V> fallback) {
V value = getter.apply(this.properties);
return (value != null ? value : fallback.apply(this.defaults));
return (value != null ? value : fallback.get());
}
}

View File

@ -24,16 +24,15 @@ import io.micrometer.core.instrument.step.StepRegistryConfig;
* Base class for {@link StepRegistryProperties} to {@link StepRegistryConfig} adapters.
*
* @param <T> The properties type
* @param <C> The config type
* @author Jon Schneider
* @author Phillip Webb
* @since 2.0.0
*/
public abstract class StepRegistryPropertiesConfigAdapter<T extends StepRegistryProperties, C extends StepRegistryConfig>
extends PropertiesConfigAdapter<T, C> implements StepRegistryConfig {
public abstract class StepRegistryPropertiesConfigAdapter<T extends StepRegistryProperties>
extends PropertiesConfigAdapter<T> implements StepRegistryConfig {
public StepRegistryPropertiesConfigAdapter(T properties, C defaults) {
super(properties, defaults);
public StepRegistryPropertiesConfigAdapter(T properties) {
super(properties);
}
@Override
@ -48,32 +47,32 @@ public abstract class StepRegistryPropertiesConfigAdapter<T extends StepRegistry
@Override
public Duration step() {
return get(T::getStep, C::step);
return get(T::getStep, StepRegistryConfig.super::step);
}
@Override
public boolean enabled() {
return get(T::getEnabled, C::enabled);
return get(T::getEnabled, StepRegistryConfig.super::enabled);
}
@Override
public Duration connectTimeout() {
return get(T::getConnectTimeout, C::connectTimeout);
return get(T::getConnectTimeout, StepRegistryConfig.super::connectTimeout);
}
@Override
public Duration readTimeout() {
return get(T::getReadTimeout, C::readTimeout);
return get(T::getReadTimeout, StepRegistryConfig.super::readTimeout);
}
@Override
public int numThreads() {
return get(T::getNumThreads, C::numThreads);
return get(T::getNumThreads, StepRegistryConfig.super::numThreads);
}
@Override
public int batchSize() {
return get(T::getBatchSize, C::batchSize);
return get(T::getBatchSize, StepRegistryConfig.super::batchSize);
}
}

View File

@ -29,12 +29,10 @@ import org.springframework.boot.actuate.autoconfigure.metrics.export.PropertiesC
* @author Phillip Webb
*/
class AtlasPropertiesConfigAdapter extends
PropertiesConfigAdapter<AtlasProperties, AtlasConfig> implements AtlasConfig {
private static final AtlasConfig DEFAULTS = (k) -> null;
PropertiesConfigAdapter<AtlasProperties> implements AtlasConfig {
AtlasPropertiesConfigAdapter(AtlasProperties properties) {
super(properties, DEFAULTS);
super(properties);
}
@Override
@ -44,68 +42,68 @@ class AtlasPropertiesConfigAdapter extends
@Override
public Duration step() {
return get(AtlasProperties::getStep, AtlasConfig::step);
return get(AtlasProperties::getStep, AtlasConfig.super::step);
}
@Override
public boolean enabled() {
return get(AtlasProperties::getEnabled, AtlasConfig::enabled);
return get(AtlasProperties::getEnabled, AtlasConfig.super::enabled);
}
@Override
public Duration connectTimeout() {
return get(AtlasProperties::getConnectTimeout, AtlasConfig::connectTimeout);
return get(AtlasProperties::getConnectTimeout, AtlasConfig.super::connectTimeout);
}
@Override
public Duration readTimeout() {
return get(AtlasProperties::getReadTimeout, AtlasConfig::readTimeout);
return get(AtlasProperties::getReadTimeout, AtlasConfig.super::readTimeout);
}
@Override
public int numThreads() {
return get(AtlasProperties::getNumThreads, AtlasConfig::numThreads);
return get(AtlasProperties::getNumThreads, AtlasConfig.super::numThreads);
}
@Override
public int batchSize() {
return get(AtlasProperties::getBatchSize, AtlasConfig::batchSize);
return get(AtlasProperties::getBatchSize, AtlasConfig.super::batchSize);
}
@Override
public String uri() {
return get(AtlasProperties::getUri, AtlasConfig::uri);
return get(AtlasProperties::getUri, AtlasConfig.super::uri);
}
@Override
public Duration meterTTL() {
return get(AtlasProperties::getMeterTimeToLive, AtlasConfig::meterTTL);
return get(AtlasProperties::getMeterTimeToLive, AtlasConfig.super::meterTTL);
}
@Override
public boolean lwcEnabled() {
return get(AtlasProperties::getLwcEnabled, AtlasConfig::lwcEnabled);
return get(AtlasProperties::getLwcEnabled, AtlasConfig.super::lwcEnabled);
}
@Override
public Duration configRefreshFrequency() {
return get(AtlasProperties::getConfigRefreshFrequency,
AtlasConfig::configRefreshFrequency);
AtlasConfig.super::configRefreshFrequency);
}
@Override
public Duration configTTL() {
return get(AtlasProperties::getConfigTimeToLive, AtlasConfig::configTTL);
return get(AtlasProperties::getConfigTimeToLive, AtlasConfig.super::configTTL);
}
@Override
public String configUri() {
return get(AtlasProperties::getConfigUri, AtlasConfig::configUri);
return get(AtlasProperties::getConfigUri, AtlasConfig.super::configUri);
}
@Override
public String evalUri() {
return get(AtlasProperties::getEvalUri, AtlasConfig::evalUri);
return get(AtlasProperties::getEvalUri, AtlasConfig.super::evalUri);
}
}

View File

@ -27,28 +27,26 @@ import org.springframework.boot.actuate.autoconfigure.metrics.export.StepRegistr
* @author Phillip Webb
*/
class DatadogPropertiesConfigAdapter
extends StepRegistryPropertiesConfigAdapter<DatadogProperties, DatadogConfig>
extends StepRegistryPropertiesConfigAdapter<DatadogProperties>
implements DatadogConfig {
private static final DatadogConfig DEFAULTS = (k) -> null;
DatadogPropertiesConfigAdapter(DatadogProperties properties) {
super(properties, DEFAULTS);
super(properties);
}
@Override
public String apiKey() {
return get(DatadogProperties::getApiKey, DatadogConfig::apiKey);
return get(DatadogProperties::getApiKey, DatadogConfig.super::apiKey);
}
@Override
public String hostTag() {
return get(DatadogProperties::getHostTag, DatadogConfig::hostTag);
return get(DatadogProperties::getHostTag, DatadogConfig.super::hostTag);
}
@Override
public String uri() {
return get(DatadogProperties::getUri, DatadogConfig::uri);
return get(DatadogProperties::getUri, DatadogConfig.super::uri);
}
}

View File

@ -31,13 +31,11 @@ import org.springframework.boot.actuate.autoconfigure.metrics.export.PropertiesC
* @author Phillip Webb
*/
class GangliaPropertiesConfigAdapter
extends PropertiesConfigAdapter<GangliaProperties, GangliaConfig>
extends PropertiesConfigAdapter<GangliaProperties>
implements GangliaConfig {
private static final GangliaConfig DEFAULTS = (k) -> null;
GangliaPropertiesConfigAdapter(GangliaProperties properties) {
super(properties, DEFAULTS);
super(properties);
}
@Override
@ -47,47 +45,47 @@ class GangliaPropertiesConfigAdapter
@Override
public boolean enabled() {
return get(GangliaProperties::getEnabled, GangliaConfig::enabled);
return get(GangliaProperties::getEnabled, GangliaConfig.super::enabled);
}
@Override
public Duration step() {
return get(GangliaProperties::getStep, GangliaConfig::step);
return get(GangliaProperties::getStep, GangliaConfig.super::step);
}
@Override
public TimeUnit rateUnits() {
return get(GangliaProperties::getRateUnits, GangliaConfig::rateUnits);
return get(GangliaProperties::getRateUnits, GangliaConfig.super::rateUnits);
}
@Override
public TimeUnit durationUnits() {
return get(GangliaProperties::getDurationUnits, GangliaConfig::durationUnits);
return get(GangliaProperties::getDurationUnits, GangliaConfig.super::durationUnits);
}
@Override
public String protocolVersion() {
return get(GangliaProperties::getProtocolVersion, GangliaConfig::protocolVersion);
return get(GangliaProperties::getProtocolVersion, GangliaConfig.super::protocolVersion);
}
@Override
public GMetric.UDPAddressingMode addressingMode() {
return get(GangliaProperties::getAddressingMode, GangliaConfig::addressingMode);
return get(GangliaProperties::getAddressingMode, GangliaConfig.super::addressingMode);
}
@Override
public int ttl() {
return get(GangliaProperties::getTimeToLive, GangliaConfig::ttl);
return get(GangliaProperties::getTimeToLive, GangliaConfig.super::ttl);
}
@Override
public String host() {
return get(GangliaProperties::getHost, GangliaConfig::host);
return get(GangliaProperties::getHost, GangliaConfig.super::host);
}
@Override
public int port() {
return get(GangliaProperties::getPort, GangliaConfig::port);
return get(GangliaProperties::getPort, GangliaConfig.super::port);
}
}

View File

@ -31,13 +31,11 @@ import org.springframework.boot.actuate.autoconfigure.metrics.export.PropertiesC
* @author Phillip Webb
*/
class GraphitePropertiesConfigAdapter
extends PropertiesConfigAdapter<GraphiteProperties, GraphiteConfig>
extends PropertiesConfigAdapter<GraphiteProperties>
implements GraphiteConfig {
private static final GraphiteConfig DEFAULTS = (k) -> null;
GraphitePropertiesConfigAdapter(GraphiteProperties properties) {
super(properties, DEFAULTS);
super(properties);
}
@Override
@ -47,37 +45,37 @@ class GraphitePropertiesConfigAdapter
@Override
public boolean enabled() {
return get(GraphiteProperties::getEnabled, GraphiteConfig::enabled);
return get(GraphiteProperties::getEnabled, GraphiteConfig.super::enabled);
}
@Override
public Duration step() {
return get(GraphiteProperties::getStep, GraphiteConfig::step);
return get(GraphiteProperties::getStep, GraphiteConfig.super::step);
}
@Override
public TimeUnit rateUnits() {
return get(GraphiteProperties::getRateUnits, GraphiteConfig::rateUnits);
return get(GraphiteProperties::getRateUnits, GraphiteConfig.super::rateUnits);
}
@Override
public TimeUnit durationUnits() {
return get(GraphiteProperties::getDurationUnits, GraphiteConfig::durationUnits);
return get(GraphiteProperties::getDurationUnits, GraphiteConfig.super::durationUnits);
}
@Override
public String host() {
return get(GraphiteProperties::getHost, GraphiteConfig::host);
return get(GraphiteProperties::getHost, GraphiteConfig.super::host);
}
@Override
public int port() {
return get(GraphiteProperties::getPort, GraphiteConfig::port);
return get(GraphiteProperties::getPort, GraphiteConfig.super::port);
}
@Override
public GraphiteProtocol protocol() {
return get(GraphiteProperties::getProtocol, GraphiteConfig::protocol);
return get(GraphiteProperties::getProtocol, GraphiteConfig.super::protocol);
}
}

View File

@ -28,48 +28,46 @@ import org.springframework.boot.actuate.autoconfigure.metrics.export.StepRegistr
* @author Phillip Webb
*/
class InfluxPropertiesConfigAdapter
extends StepRegistryPropertiesConfigAdapter<InfluxProperties, InfluxConfig>
extends StepRegistryPropertiesConfigAdapter<InfluxProperties>
implements InfluxConfig {
private static final InfluxConfig DEFAULTS = (k) -> null;
InfluxPropertiesConfigAdapter(InfluxProperties properties) {
super(properties, DEFAULTS);
super(properties);
}
@Override
public String db() {
return get(InfluxProperties::getDb, InfluxConfig::db);
return get(InfluxProperties::getDb, InfluxConfig.super::db);
}
@Override
public InfluxConsistency consistency() {
return get(InfluxProperties::getConsistency, InfluxConfig::consistency);
return get(InfluxProperties::getConsistency, InfluxConfig.super::consistency);
}
@Override
public String userName() {
return get(InfluxProperties::getUserName, InfluxConfig::userName);
return get(InfluxProperties::getUserName, InfluxConfig.super::userName);
}
@Override
public String password() {
return get(InfluxProperties::getPassword, InfluxConfig::password);
return get(InfluxProperties::getPassword, InfluxConfig.super::password);
}
@Override
public String retentionPolicy() {
return get(InfluxProperties::getRetentionPolicy, InfluxConfig::retentionPolicy);
return get(InfluxProperties::getRetentionPolicy, InfluxConfig.super::retentionPolicy);
}
@Override
public String uri() {
return get(InfluxProperties::getUri, InfluxConfig::uri);
return get(InfluxProperties::getUri, InfluxConfig.super::uri);
}
@Override
public boolean compressed() {
return get(InfluxProperties::getCompressed, InfluxConfig::compressed);
return get(InfluxProperties::getCompressed, InfluxConfig.super::compressed);
}
}

View File

@ -29,13 +29,11 @@ import org.springframework.boot.actuate.autoconfigure.metrics.export.PropertiesC
* @author Phillip Webb
*/
class PrometheusPropertiesConfigAdapter
extends PropertiesConfigAdapter<PrometheusProperties, PrometheusConfig>
extends PropertiesConfigAdapter<PrometheusProperties>
implements PrometheusConfig {
private static final PrometheusConfig DEFAULTS = (key) -> null;
PrometheusPropertiesConfigAdapter(PrometheusProperties properties) {
super(properties, DEFAULTS);
super(properties);
}
@Override
@ -45,12 +43,12 @@ class PrometheusPropertiesConfigAdapter
@Override
public boolean descriptions() {
return get(PrometheusProperties::getDescriptions, PrometheusConfig::descriptions);
return get(PrometheusProperties::getDescriptions, PrometheusConfig.super::descriptions);
}
@Override
public Duration step() {
return get(PrometheusProperties::getStep, PrometheusConfig::step);
return get(PrometheusProperties::getStep, PrometheusConfig.super::step);
}
}

View File

@ -29,11 +29,10 @@ import org.springframework.boot.actuate.autoconfigure.metrics.export.PropertiesC
* @since 2.0.0
*/
public class SimplePropertiesConfigAdapter extends
PropertiesConfigAdapter<SimpleProperties, SimpleConfig> implements SimpleConfig {
private static final SimpleConfig DEFAULTS = (key) -> null;
PropertiesConfigAdapter<SimpleProperties> implements SimpleConfig {
public SimplePropertiesConfigAdapter(SimpleProperties properties) {
super(properties, DEFAULTS);
super(properties);
}
@Override
@ -43,11 +42,11 @@ public class SimplePropertiesConfigAdapter extends
@Override
public boolean enabled() {
return get(SimpleProperties::getEnabled, SimpleConfig::enabled);
return get(SimpleProperties::getEnabled, SimpleConfig.super::enabled);
}
@Override
public Duration step() {
return get(SimpleProperties::getStep, SimpleConfig::step);
return get(SimpleProperties::getStep, SimpleConfig.super::step);
}
}

View File

@ -30,12 +30,10 @@ import org.springframework.boot.actuate.autoconfigure.metrics.export.PropertiesC
* @since 2.0.0
*/
public class StatsdPropertiesConfigAdapter extends
PropertiesConfigAdapter<StatsdProperties, StatsdConfig> implements StatsdConfig {
private static final StatsdConfig DEFAULTS = (key) -> null;
PropertiesConfigAdapter<StatsdProperties> implements StatsdConfig {
public StatsdPropertiesConfigAdapter(StatsdProperties properties) {
super(properties, DEFAULTS);
super(properties);
}
@Override
@ -45,37 +43,37 @@ public class StatsdPropertiesConfigAdapter extends
@Override
public StatsdFlavor flavor() {
return get(StatsdProperties::getFlavor, StatsdConfig::flavor);
return get(StatsdProperties::getFlavor, StatsdConfig.super::flavor);
}
@Override
public boolean enabled() {
return get(StatsdProperties::getEnabled, StatsdConfig::enabled);
return get(StatsdProperties::getEnabled, StatsdConfig.super::enabled);
}
@Override
public String host() {
return get(StatsdProperties::getHost, StatsdConfig::host);
return get(StatsdProperties::getHost, StatsdConfig.super::host);
}
@Override
public int port() {
return get(StatsdProperties::getPort, StatsdConfig::port);
return get(StatsdProperties::getPort, StatsdConfig.super::port);
}
@Override
public int maxPacketLength() {
return get(StatsdProperties::getMaxPacketLength, StatsdConfig::maxPacketLength);
return get(StatsdProperties::getMaxPacketLength, StatsdConfig.super::maxPacketLength);
}
@Override
public Duration pollingFrequency() {
return get(StatsdProperties::getPollingFrequency, StatsdConfig::pollingFrequency);
return get(StatsdProperties::getPollingFrequency, StatsdConfig.super::pollingFrequency);
}
@Override
public int queueSize() {
return get(StatsdProperties::getQueueSize, StatsdConfig::queueSize);
return get(StatsdProperties::getQueueSize, StatsdConfig.super::queueSize);
}
}

View File

@ -0,0 +1,64 @@
/*
* Copyright 2012-2017 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.datadog;
import io.micrometer.core.instrument.composite.CompositeMeterRegistry;
import io.micrometer.datadog.DatadogMeterRegistry;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.actuate.autoconfigure.metrics.MetricsAutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.test.context.junit4.SpringRunner;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link DatadogExportConfiguration}.
*
* @author Nikolay Rybak
*/
@RunWith(SpringRunner.class)
public class DatadogExportConfigurationTests {
/**
* Validated that {@link DatadogMeterRegistry} can be started by only specifying Datadog API key.
*/
@Test
public void datadogMeterRegistryIsConfiguredWithApiKeyOnly() {
new ApplicationContextRunner()
.withPropertyValues("spring.metrics.export.atlas.enabled=false",
"spring.metrics.export.datadog.enabled=true",
"spring.metrics.export.ganglia.enabled=false",
"spring.metrics.export.graphite.enabled=false",
"spring.metrics.export.influx.enabled=false",
"spring.metrics.export.jmx.enabled=false",
"spring.metrics.export.prometheus.enabled=false",
"spring.metrics.export.statsd.enabled=false",
"spring.metrics.export.datadog.api-key=APIKEY")
.withConfiguration(AutoConfigurations.of(MetricsAutoConfiguration.class))
.run((context) -> {
CompositeMeterRegistry meterRegistry = context
.getBean(CompositeMeterRegistry.class);
assertThat(meterRegistry.getRegistries()).hasSize(1);
assertThat(meterRegistry.getRegistries())
.hasOnlyElementsOfType(DatadogMeterRegistry.class);
});
}
}