Polish "Add more customization options for InfluxDB"

See gh-25319
pull/25400/head
Stephane Nicoll 4 years ago
parent 8be0b87273
commit d9dcfeba5c

@ -17,7 +17,6 @@
package org.springframework.boot.autoconfigure.influx; package org.springframework.boot.autoconfigure.influx;
import okhttp3.OkHttpClient; import okhttp3.OkHttpClient;
import org.influxdb.BatchOptions;
import org.influxdb.InfluxDB; import org.influxdb.InfluxDB;
import org.influxdb.impl.InfluxDBImpl; import org.influxdb.impl.InfluxDBImpl;
@ -27,7 +26,6 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.context.properties.PropertyMapper;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
@ -51,29 +49,10 @@ public class InfluxDbAutoConfiguration {
ObjectProvider<InfluxDbCustomizer> customizers) { ObjectProvider<InfluxDbCustomizer> customizers) {
InfluxDB influxDb = new InfluxDBImpl(properties.getUrl(), properties.getUser(), properties.getPassword(), InfluxDB influxDb = new InfluxDBImpl(properties.getUrl(), properties.getUser(), properties.getPassword(),
determineBuilder(builder.getIfAvailable())); determineBuilder(builder.getIfAvailable()));
PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull();
map.from(properties::getConsistency).to(influxDb::setConsistency);
map.from(properties::getDatabase).to(influxDb::setDatabase);
map.from(properties::getLog).to(influxDb::setLogLevel);
map.from(properties::getRetentionPolicy).to(influxDb::setRetentionPolicy);
map.from(properties.isGzipEnabled()).whenTrue().toCall(influxDb::enableGzip);
if (properties.getBatch().isEnabled()) {
BatchOptions batchOptions = mapBatchOptions(properties);
influxDb.enableBatch(batchOptions);
}
customizers.orderedStream().forEach((customizer) -> customizer.customize(influxDb)); customizers.orderedStream().forEach((customizer) -> customizer.customize(influxDb));
return influxDb; return influxDb;
} }
private BatchOptions mapBatchOptions(InfluxDbProperties properties) {
InfluxDbProperties.Batch batch = properties.getBatch();
return BatchOptions.DEFAULTS.actions(batch.getActions())
.flushDuration(Long.valueOf(batch.getFlushDuration().toMillis()).intValue())
.jitterDuration(Long.valueOf(batch.getJitterDuration().toMillis()).intValue())
.bufferLimit(batch.getBufferLimit()).consistency(batch.getConsistency()).precision(batch.getPrecision())
.dropActionsOnQueueExhaustion(batch.isDropActionsOnQueueExhaustion());
}
private static OkHttpClient.Builder determineBuilder(InfluxDbOkHttpClientBuilderProvider builder) { private static OkHttpClient.Builder determineBuilder(InfluxDbOkHttpClientBuilderProvider builder) {
if (builder != null) { if (builder != null) {
return builder.get(); return builder.get();

@ -19,7 +19,8 @@ package org.springframework.boot.autoconfigure.influx;
import org.influxdb.InfluxDB; import org.influxdb.InfluxDB;
/** /**
* Callback interface for customizing {@code InfluxDB} beans. * Callback interface that can be implemented by beans wishing to further customize
* {@code InfluxDB} whilst retaining default auto-configuration.
* *
* @author Eddú Meléndez * @author Eddú Meléndez
* @since 2.5.0 * @since 2.5.0
@ -29,7 +30,7 @@ public interface InfluxDbCustomizer {
/** /**
* Customize the {@link InfluxDB}. * Customize the {@link InfluxDB}.
* @param influxDB the batch options to customize * @param influxDB the influxDB instance to customize
*/ */
void customize(InfluxDB influxDB); void customize(InfluxDB influxDB);

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2021 the original author or authors. * Copyright 2012-2019 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -16,11 +16,6 @@
package org.springframework.boot.autoconfigure.influx; package org.springframework.boot.autoconfigure.influx;
import java.time.Duration;
import java.util.concurrent.TimeUnit;
import org.influxdb.InfluxDB;
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationProperties;
/** /**
@ -28,7 +23,6 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
* *
* @author Sergey Kuptsov * @author Sergey Kuptsov
* @author Stephane Nicoll * @author Stephane Nicoll
* @author Eddú Meléndez
* @since 2.0.0 * @since 2.0.0
*/ */
@ConfigurationProperties(prefix = "spring.influx") @ConfigurationProperties(prefix = "spring.influx")
@ -49,36 +43,6 @@ public class InfluxDbProperties {
*/ */
private String password; private String password;
/**
* Consistency level.
*/
private InfluxDB.ConsistencyLevel consistency;
/**
* Database name.
*/
private String database;
/**
* Log level.
*/
private InfluxDB.LogLevel log;
/**
* Retention policy.
*/
private String retentionPolicy;
/**
* Whether to enable Gzip compression.
*/
private boolean gzipEnabled;
/**
* Batch configuration.
*/
private final Batch batch = new Batch();
public String getUrl() { public String getUrl() {
return this.url; return this.url;
} }
@ -103,156 +67,4 @@ public class InfluxDbProperties {
this.password = password; this.password = password;
} }
public InfluxDB.ConsistencyLevel getConsistency() {
return this.consistency;
}
public void setConsistency(InfluxDB.ConsistencyLevel consistency) {
this.consistency = consistency;
}
public String getDatabase() {
return this.database;
}
public void setDatabase(String database) {
this.database = database;
}
public InfluxDB.LogLevel getLog() {
return this.log;
}
public void setLog(InfluxDB.LogLevel log) {
this.log = log;
}
public String getRetentionPolicy() {
return this.retentionPolicy;
}
public void setRetentionPolicy(String retentionPolicy) {
this.retentionPolicy = retentionPolicy;
}
public boolean isGzipEnabled() {
return this.gzipEnabled;
}
public void setGzipEnabled(boolean gzipEnabled) {
this.gzipEnabled = gzipEnabled;
}
public Batch getBatch() {
return this.batch;
}
public static class Batch {
/**
* Whether to enable Batch configuration.
*/
private boolean enabled;
/**
* Number of actions to collect.
*/
private int actions = 1000;
/**
* Time to wait.
*/
private Duration flushDuration = Duration.ofMillis(1000);
/**
* Time to jitter the batch flush interval.
*/
private Duration jitterDuration = Duration.ofMillis(0);
/**
* Number of points stored in the retry buffer.
*/
private int bufferLimit = 10000;
/**
* Cluster consistency.
*/
private InfluxDB.ConsistencyLevel consistency = InfluxDB.ConsistencyLevel.ONE;
/**
* Precision to use for the whole batch.
*/
private TimeUnit precision = TimeUnit.NANOSECONDS;
/**
* Whether to enable dropped actions.
*/
private boolean dropActionsOnQueueExhaustion = false;
public boolean isEnabled() {
return this.enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public int getActions() {
return this.actions;
}
public void setActions(int actions) {
this.actions = actions;
}
public Duration getFlushDuration() {
return this.flushDuration;
}
public void setFlushDuration(Duration flushDuration) {
this.flushDuration = flushDuration;
}
public Duration getJitterDuration() {
return this.jitterDuration;
}
public void setJitterDuration(Duration jitterDuration) {
this.jitterDuration = jitterDuration;
}
public int getBufferLimit() {
return this.bufferLimit;
}
public void setBufferLimit(int bufferLimit) {
this.bufferLimit = bufferLimit;
}
public InfluxDB.ConsistencyLevel getConsistency() {
return this.consistency;
}
public void setConsistency(InfluxDB.ConsistencyLevel consistency) {
this.consistency = consistency;
}
public TimeUnit getPrecision() {
return this.precision;
}
public void setPrecision(TimeUnit precision) {
this.precision = precision;
}
public boolean isDropActionsOnQueueExhaustion() {
return this.dropActionsOnQueueExhaustion;
}
public void setDropActionsOnQueueExhaustion(boolean dropActionsOnQueueExhaustion) {
this.dropActionsOnQueueExhaustion = dropActionsOnQueueExhaustion;
}
}
} }

@ -19,9 +19,7 @@ package org.springframework.boot.autoconfigure.influx;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import okhttp3.OkHttpClient; import okhttp3.OkHttpClient;
import org.influxdb.BatchOptions;
import org.influxdb.InfluxDB; import org.influxdb.InfluxDB;
import org.influxdb.impl.BatchProcessor;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import retrofit2.Retrofit; import retrofit2.Retrofit;
@ -48,21 +46,21 @@ class InfluxDbAutoConfigurationTests {
@Test @Test
void influxDbRequiresUrl() { void influxDbRequiresUrl() {
this.contextRunner.run((context) -> assertThat(context.getBeansOfType(InfluxDB.class)).isEmpty()); this.contextRunner.run((context) -> assertThat(context).doesNotHaveBean(InfluxDB.class));
} }
@Test @Test
void influxDbCanBeCustomized() { void influxDbCanBeCustomized() {
this.contextRunner this.contextRunner
.withPropertyValues("spring.influx.url=http://localhost", "spring.influx.password:password", .withPropertyValues("spring.influx.url=http://localhost", "spring.influx.user=user",
"spring.influx.user:user") "spring.influx.password=password")
.run(((context) -> assertThat(context.getBeansOfType(InfluxDB.class)).hasSize(1))); .run((context) -> assertThat(context).hasSingleBean(InfluxDB.class));
} }
@Test @Test
void influxDbCanBeCreatedWithoutCredentials() { void influxDbCanBeCreatedWithoutCredentials() {
this.contextRunner.withPropertyValues("spring.influx.url=http://localhost").run((context) -> { this.contextRunner.withPropertyValues("spring.influx.url=http://localhost").run((context) -> {
assertThat(context.getBeansOfType(InfluxDB.class)).hasSize(1); assertThat(context).hasSingleBean(InfluxDB.class);
int readTimeout = getReadTimeoutProperty(context); int readTimeout = getReadTimeoutProperty(context);
assertThat(readTimeout).isEqualTo(10_000); assertThat(readTimeout).isEqualTo(10_000);
}); });
@ -72,87 +70,20 @@ class InfluxDbAutoConfigurationTests {
void influxDbWithOkHttpClientBuilderProvider() { void influxDbWithOkHttpClientBuilderProvider() {
this.contextRunner.withUserConfiguration(CustomOkHttpClientBuilderProviderConfig.class) this.contextRunner.withUserConfiguration(CustomOkHttpClientBuilderProviderConfig.class)
.withPropertyValues("spring.influx.url=http://localhost").run((context) -> { .withPropertyValues("spring.influx.url=http://localhost").run((context) -> {
assertThat(context.getBeansOfType(InfluxDB.class)).hasSize(1); assertThat(context).hasSingleBean(InfluxDB.class);
int readTimeout = getReadTimeoutProperty(context); int readTimeout = getReadTimeoutProperty(context);
assertThat(readTimeout).isEqualTo(40_000); assertThat(readTimeout).isEqualTo(40_000);
}); });
} }
@Test @Test
void influxDbWithDatabase() { void influxDbWithCustomizer() {
this.contextRunner.withPropertyValues("spring.influx.url=http://localhost", "spring.influx.database:sample-db") this.contextRunner.withBean(InfluxDbCustomizer.class, () -> (influxDb) -> influxDb.setDatabase("test"))
.withPropertyValues("spring.influx.url=http://localhost", "spring.influx.database=sample-db")
.run((context) -> { .run((context) -> {
assertThat(context.getBeansOfType(InfluxDB.class)).hasSize(1); assertThat(context).hasSingleBean(InfluxDB.class);
InfluxDB influxDb = context.getBean(InfluxDB.class); InfluxDB influxDb = context.getBean(InfluxDB.class);
String database = (String) ReflectionTestUtils.getField(influxDb, "database"); assertThat(influxDb).hasFieldOrPropertyWithValue("database", "test");
assertThat(database).isEqualTo("sample-db");
});
}
@Test
void influxDbWithRetentionPolicy() {
this.contextRunner
.withPropertyValues("spring.influx.url=http://localhost", "spring.influx.retention-policy:two_hours")
.run((context) -> {
assertThat(context.getBeansOfType(InfluxDB.class)).hasSize(1);
InfluxDB influxDb = context.getBean(InfluxDB.class);
String retentionPolicy = (String) ReflectionTestUtils.getField(influxDb, "retentionPolicy");
assertThat(retentionPolicy).isEqualTo("two_hours");
});
}
@Test
void influxDbWithLogLevel() {
this.contextRunner.withPropertyValues("spring.influx.url=http://localhost", "spring.influx.log:basic")
.run((context) -> {
assertThat(context.getBeansOfType(InfluxDB.class)).hasSize(1);
InfluxDB influxDb = context.getBean(InfluxDB.class);
InfluxDB.LogLevel log = (InfluxDB.LogLevel) ReflectionTestUtils.getField(influxDb, "logLevel");
assertThat(log).isEqualTo(InfluxDB.LogLevel.BASIC);
});
}
@Test
void influxDbWithConsistency() {
this.contextRunner.withPropertyValues("spring.influx.url=http://localhost", "spring.influx.consistency:all")
.run((context) -> {
assertThat(context.getBeansOfType(InfluxDB.class)).hasSize(1);
InfluxDB influxDb = context.getBean(InfluxDB.class);
InfluxDB.ConsistencyLevel consistency = (InfluxDB.ConsistencyLevel) ReflectionTestUtils
.getField(influxDb, "consistency");
assertThat(consistency).isEqualTo(InfluxDB.ConsistencyLevel.ALL);
});
}
@Test
void influxDbWithBatchOptions() {
this.contextRunner.withPropertyValues("spring.influx.url=http://localhost", "spring.influx.batch.enabled:true",
"spring.influx.batch.actions:50", "spring.influx.batch.flush-duration:50").run((context) -> {
assertThat(context.getBeansOfType(InfluxDB.class)).hasSize(1);
InfluxDB influxDb = context.getBean(InfluxDB.class);
BatchProcessor batchProcessor = (BatchProcessor) ReflectionTestUtils.getField(influxDb,
"batchProcessor");
int actions = (int) ReflectionTestUtils.getField(batchProcessor, "actions");
int flushInterval = (int) ReflectionTestUtils.getField(batchProcessor, "flushInterval");
assertThat(actions).isEqualTo(50);
assertThat(flushInterval).isEqualTo(50);
});
}
@Test
void influxDbWithBatchOptionsCustomizer() {
this.contextRunner.withUserConfiguration(CustomInfluxDbBatchOptionsCustomizerConfig.class)
.withPropertyValues("spring.influx.url=http://localhost").run((context) -> {
assertThat(context.getBeansOfType(InfluxDB.class)).hasSize(1);
InfluxDB influxDb = context.getBean(InfluxDB.class);
BatchProcessor batchProcessor = (BatchProcessor) ReflectionTestUtils.getField(influxDb,
"batchProcessor");
int actions = (int) ReflectionTestUtils.getField(batchProcessor, "actions");
int flushInterval = (int) ReflectionTestUtils.getField(batchProcessor, "flushInterval");
int jitterInterval = (int) ReflectionTestUtils.getField(batchProcessor, "jitterInterval");
assertThat(actions).isEqualTo(20);
assertThat(flushInterval).isEqualTo(20);
assertThat(jitterInterval).isEqualTo(20);
}); });
} }
@ -173,17 +104,4 @@ class InfluxDbAutoConfigurationTests {
} }
@Configuration(proxyBeanMethods = false)
static class CustomInfluxDbBatchOptionsCustomizerConfig {
@Bean
InfluxDbCustomizer influxDbBatchOptionsCustomizer() {
return (influxDb) -> {
BatchOptions batchOptions = BatchOptions.DEFAULTS.actions(20).flushDuration(20).jitterDuration(20);
influxDb.enableBatch(batchOptions);
};
}
}
} }

@ -1,47 +0,0 @@
/*
* Copyright 2012-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.autoconfigure.influx;
import org.influxdb.BatchOptions;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link InfluxDbProperties}.
*
* @author Eddú Meléndez
*/
class InfluxDbPropertiesTests {
@Test
void defaultValuesAreConsistent() {
InfluxDbProperties properties = new InfluxDbProperties();
BatchOptions batchOptions = BatchOptions.DEFAULTS;
assertThat(properties.getBatch().getActions()).isEqualTo(batchOptions.getActions());
assertThat(Long.valueOf(properties.getBatch().getFlushDuration().toMillis()).intValue())
.isEqualTo(batchOptions.getFlushDuration());
assertThat(Long.valueOf(properties.getBatch().getJitterDuration().toMillis()).intValue())
.isEqualTo(batchOptions.getJitterDuration());
assertThat(properties.getBatch().getBufferLimit()).isEqualTo(batchOptions.getBufferLimit());
assertThat(properties.getBatch().getConsistency()).isEqualTo(batchOptions.getConsistency());
assertThat(properties.getBatch().getPrecision()).isEqualTo(batchOptions.getPrecision());
assertThat(properties.getBatch().isDropActionsOnQueueExhaustion())
.isEqualTo(batchOptions.isDropActionsOnQueueExhaustion());
}
}

@ -4922,6 +4922,8 @@ If the connection to InfluxDB requires a user and password, you can set the `spr
InfluxDB relies on OkHttp. InfluxDB relies on OkHttp.
If you need to tune the http client `InfluxDB` uses behind the scenes, you can register an `InfluxDbOkHttpClientBuilderProvider` bean. If you need to tune the http client `InfluxDB` uses behind the scenes, you can register an `InfluxDbOkHttpClientBuilderProvider` bean.
If you need more control over the configuration, consider registering a `InfluxDbCustomizer` bean.
[[boot-features-caching]] [[boot-features-caching]]

Loading…
Cancel
Save