Add health indicator for reactive MongoDB

See gh-11997
pull/12021/merge
Yulin Qin 7 years ago committed by Stephane Nicoll
parent a02fdc755e
commit eee2694648

@ -248,6 +248,16 @@
<artifactId>liquibase-core</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongodb-driver-async</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongodb-driver-reactivestreams</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>

@ -0,0 +1,67 @@
/*
* Copyright 2012-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.actuate.autoconfigure.mongo;
import java.util.Map;
import org.springframework.boot.actuate.autoconfigure.health.CompositeReactiveHealthIndicatorConfiguration;
import org.springframework.boot.actuate.autoconfigure.health.ConditionalOnEnabledHealthIndicator;
import org.springframework.boot.actuate.autoconfigure.health.HealthIndicatorAutoConfiguration;
import org.springframework.boot.actuate.health.ReactiveHealthIndicator;
import org.springframework.boot.actuate.mongo.MongoReactiveHealthIndicator;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.data.mongo.MongoReactiveDataAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.core.ReactiveMongoTemplate;
/**
* {@link EnableAutoConfiguration Auto-configuration} for {@link MongoReactiveHealthIndicator}.
*
* @author Yulin Qin
* @since 2.0.0
*/
@Configuration
@ConditionalOnClass(ReactiveMongoTemplate.class)
@ConditionalOnBean(ReactiveMongoTemplate.class)
@ConditionalOnEnabledHealthIndicator("mongo")
@AutoConfigureBefore(HealthIndicatorAutoConfiguration.class)
@AutoConfigureAfter(MongoReactiveDataAutoConfiguration.class)
public class MongoReactiveHealthIndicatorAutoConfiguration extends
CompositeReactiveHealthIndicatorConfiguration<MongoReactiveHealthIndicator, ReactiveMongoTemplate> {
private final Map<String, ReactiveMongoTemplate> reactiveMongoTemplate;
public MongoReactiveHealthIndicatorAutoConfiguration(
Map<String, ReactiveMongoTemplate> reactiveMongoTemplate) {
this.reactiveMongoTemplate = reactiveMongoTemplate;
}
@Bean
@ConditionalOnMissingBean(name = "mongoReactiveHealthIndicator")
public ReactiveHealthIndicator mongoReactiveHealthIndicator() {
return createHealthIndicator(this.reactiveMongoTemplate);
}
}

@ -53,6 +53,7 @@ org.springframework.boot.actuate.autoconfigure.metrics.web.client.RestTemplateMe
org.springframework.boot.actuate.autoconfigure.metrics.web.reactive.WebFluxMetricsAutoConfiguration,\
org.springframework.boot.actuate.autoconfigure.metrics.web.servlet.WebMvcMetricsAutoConfiguration,\
org.springframework.boot.actuate.autoconfigure.mongo.MongoHealthIndicatorAutoConfiguration,\
org.springframework.boot.actuate.autoconfigure.mongo.MongoReactiveHealthIndicatorAutoConfiguration,\
org.springframework.boot.actuate.autoconfigure.neo4j.Neo4jHealthIndicatorAutoConfiguration,\
org.springframework.boot.actuate.autoconfigure.redis.RedisHealthIndicatorAutoConfiguration,\
org.springframework.boot.actuate.autoconfigure.scheduling.ScheduledTasksEndpointAutoConfiguration,\

@ -0,0 +1,67 @@
/*
* Copyright 2012-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.actuate.autoconfigure.mongo;
import org.junit.Test;
import org.springframework.boot.actuate.autoconfigure.health.HealthIndicatorAutoConfiguration;
import org.springframework.boot.actuate.health.ApplicationHealthIndicator;
import org.springframework.boot.actuate.mongo.MongoHealthIndicator;
import org.springframework.boot.actuate.mongo.MongoReactiveHealthIndicator;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration;
import org.springframework.boot.autoconfigure.data.mongo.MongoReactiveDataAutoConfiguration;
import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration;
import org.springframework.boot.autoconfigure.mongo.MongoReactiveAutoConfiguration;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link MongoReactiveHealthIndicatorAutoConfiguration}
*
* @author Yulin Qin
*/
public class MongoReactiveHealthIndicatorAutoConfigurationTests {
private ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(
MongoAutoConfiguration.class,
MongoDataAutoConfiguration.class,
MongoReactiveAutoConfiguration.class,
MongoReactiveDataAutoConfiguration.class,
MongoReactiveHealthIndicatorAutoConfiguration.class,
HealthIndicatorAutoConfiguration.class));
@Test
public void runShouldCreateIndicator() {
this.contextRunner.run(
(context) -> assertThat(context).hasSingleBean(MongoReactiveHealthIndicator.class)
.doesNotHaveBean(MongoHealthIndicator.class)
.doesNotHaveBean(ApplicationHealthIndicator.class));
}
@Test
public void runWhenDisabledShouldNotCreateIndicator() {
this.contextRunner.withPropertyValues("management.health.mongo.enabled:false")
.run((context) -> assertThat(context)
.doesNotHaveBean(MongoReactiveHealthIndicator.class)
.doesNotHaveBean(MongoHealthIndicator.class)
.hasSingleBean(ApplicationHealthIndicator.class));
}
}

@ -0,0 +1,55 @@
/*
* Copyright 2012-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.actuate.mongo;
import org.bson.Document;
import reactor.core.publisher.Mono;
import org.springframework.boot.actuate.health.AbstractReactiveHealthIndicator;
import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.ReactiveHealthIndicator;
import org.springframework.data.mongodb.core.ReactiveMongoTemplate;
import org.springframework.util.Assert;
/**
* A {@link ReactiveHealthIndicator} for Mongo.
*
* @author Yulin Qin
* @since 2.0.0
*/
public class MongoReactiveHealthIndicator extends AbstractReactiveHealthIndicator {
private final ReactiveMongoTemplate reactiveMongoTemplate;
public MongoReactiveHealthIndicator(ReactiveMongoTemplate reactiveMongoTemplate) {
Assert.notNull(reactiveMongoTemplate, "ReactiveMongoTemplate must not be null");
this.reactiveMongoTemplate = reactiveMongoTemplate;
}
@Override
protected Mono<Health> doHealthCheck(Health.Builder builder) {
Mono<Document> documentMono = this.reactiveMongoTemplate.executeCommand("{ buildInfo: 1 }");
return documentMono.map(document -> up(builder, document));
}
private Health up(Health.Builder builder, Document document) {
return builder.up().withDetail("version", document.getString("version")).build();
}
}

@ -0,0 +1,70 @@
/*
* Copyright 2012-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.actuate.mongo;
import com.mongodb.MongoException;
import org.bson.Document;
import org.junit.Test;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.Status;
import org.springframework.data.mongodb.core.ReactiveMongoTemplate;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
/**
* Tests for {@link MongoReactiveHealthIndicator}.
*
* @author Yulin Qin
*/
public class MongoReactiveHealthIndicatorTest {
@Test
public void testMongoIsUp() throws Exception {
Document document = mock(Document.class);
ReactiveMongoTemplate reactiveMongoTemplate = mock(ReactiveMongoTemplate.class);
given(reactiveMongoTemplate.executeCommand("{ buildInfo: 1 }")).willReturn(Mono.just(document));
given(document.getString("version")).willReturn("2.6.4");
MongoReactiveHealthIndicator mongoReactiveHealthIndicator = new MongoReactiveHealthIndicator(reactiveMongoTemplate);
Mono<Health> health = mongoReactiveHealthIndicator.health();
StepVerifier.create(health).consumeNextWith((h) -> {
assertThat(h.getStatus()).isEqualTo(Status.UP);
assertThat(h.getDetails()).containsOnlyKeys("version");
assertThat(h.getDetails().get("version")).isEqualTo("2.6.4");
}).verifyComplete();
}
@Test
public void testMongoIsDown() throws Exception {
ReactiveMongoTemplate reactiveMongoTemplate = mock(ReactiveMongoTemplate.class);
given(reactiveMongoTemplate.executeCommand("{ buildInfo: 1 }")).willThrow(new MongoException("Connection failed"));
MongoReactiveHealthIndicator mongoReactiveHealthIndicator = new MongoReactiveHealthIndicator(reactiveMongoTemplate);
Mono<Health> health = mongoReactiveHealthIndicator.health();
StepVerifier.create(health).consumeNextWith((h) -> {
assertThat(h.getStatus()).isEqualTo(Status.DOWN);
assertThat(h.getDetails()).containsOnlyKeys("error");
assertThat(h.getDetails().get("error")).isEqualTo("Connection failed");
}).verifyComplete();
}
}

@ -1,5 +1,5 @@
/*
* Copyright 2012-2018 the original author or authors.
* 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.
@ -32,6 +32,7 @@ import org.springframework.data.mongodb.core.ReactiveMongoTemplate;
import org.springframework.data.mongodb.core.SimpleReactiveMongoDatabaseFactory;
import org.springframework.data.mongodb.core.convert.MongoConverter;
/**
* {@link EnableAutoConfiguration Auto-configuration} for Spring Data's reactive mongo
* support.
@ -43,6 +44,7 @@ import org.springframework.data.mongodb.core.convert.MongoConverter;
* to the {@literal test} database.
*
* @author Mark Paluch
* @author Yulin Qin
* @since 2.0.0
*/
@Configuration
@ -73,5 +75,4 @@ public class MongoReactiveDataAutoConfiguration {
MongoConverter converter) {
return new ReactiveMongoTemplate(reactiveMongoDatabaseFactory, converter);
}
}

Loading…
Cancel
Save