Add a HealthIndicator for Solr

pull/931/merge
Andy Wilkinson 11 years ago
parent d673002c2e
commit b76a519f65

@ -50,7 +50,7 @@
<groupId>javax.servlet</groupId> <groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId> <artifactId>javax.servlet-api</artifactId>
<optional>true</optional> <optional>true</optional>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.hibernate</groupId> <groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId> <artifactId>hibernate-validator</artifactId>
@ -71,6 +71,11 @@
<artifactId>spring-webmvc</artifactId> <artifactId>spring-webmvc</artifactId>
<optional>true</optional> <optional>true</optional>
</dependency> </dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb</artifactId>
<optional>true</optional>
</dependency>
<dependency> <dependency>
<groupId>org.springframework.data</groupId> <groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId> <artifactId>spring-data-redis</artifactId>
@ -78,7 +83,7 @@
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.springframework.data</groupId> <groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb</artifactId> <artifactId>spring-data-solr</artifactId>
<optional>true</optional> <optional>true</optional>
</dependency> </dependency>
<dependency> <dependency>

@ -21,6 +21,7 @@ import java.util.Map;
import javax.sql.DataSource; import javax.sql.DataSource;
import org.apache.solr.client.solrj.SolrServer;
import org.springframework.amqp.rabbit.core.RabbitTemplate; import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
@ -32,6 +33,7 @@ import org.springframework.boot.actuate.health.OrderedHealthAggregator;
import org.springframework.boot.actuate.health.RabbitHealthIndicator; import org.springframework.boot.actuate.health.RabbitHealthIndicator;
import org.springframework.boot.actuate.health.RedisHealthIndicator; import org.springframework.boot.actuate.health.RedisHealthIndicator;
import org.springframework.boot.actuate.health.SimpleDataSourceHealthIndicator; import org.springframework.boot.actuate.health.SimpleDataSourceHealthIndicator;
import org.springframework.boot.actuate.health.SolrHealthIndicator;
import org.springframework.boot.actuate.health.VanillaHealthIndicator; import org.springframework.boot.actuate.health.VanillaHealthIndicator;
import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.AutoConfigureBefore; import org.springframework.boot.autoconfigure.AutoConfigureBefore;
@ -44,6 +46,7 @@ import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration; import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration;
import org.springframework.boot.autoconfigure.mongo.MongoDataAutoConfiguration; import org.springframework.boot.autoconfigure.mongo.MongoDataAutoConfiguration;
import org.springframework.boot.autoconfigure.redis.RedisAutoConfiguration; import org.springframework.boot.autoconfigure.redis.RedisAutoConfiguration;
import org.springframework.boot.autoconfigure.solr.SolrAutoConfiguration;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.MongoTemplate;
@ -51,15 +54,16 @@ import org.springframework.data.redis.connection.RedisConnectionFactory;
/** /**
* {@link EnableAutoConfiguration Auto-configuration} for {@link HealthIndicator}s. * {@link EnableAutoConfiguration Auto-configuration} for {@link HealthIndicator}s.
* *
* @author Christian Dupuis * @author Christian Dupuis
* @author Andy Wilkinson
* @since 1.1.0 * @since 1.1.0
*/ */
@Configuration @Configuration
@AutoConfigureBefore({ EndpointAutoConfiguration.class }) @AutoConfigureBefore({ EndpointAutoConfiguration.class })
@AutoConfigureAfter({ DataSourceAutoConfiguration.class, MongoAutoConfiguration.class, @AutoConfigureAfter({ DataSourceAutoConfiguration.class, MongoAutoConfiguration.class,
MongoDataAutoConfiguration.class, RedisAutoConfiguration.class, MongoDataAutoConfiguration.class, RedisAutoConfiguration.class,
RabbitAutoConfiguration.class }) RabbitAutoConfiguration.class, SolrAutoConfiguration.class })
public class HealthIndicatorAutoConfiguration { public class HealthIndicatorAutoConfiguration {
@Value("${health.status.order:}") @Value("${health.status.order:}")
@ -199,4 +203,33 @@ public class HealthIndicatorAutoConfiguration {
} }
} }
@Configuration
@ConditionalOnBean(SolrServer.class)
@ConditionalOnExpression("${health.solr.enabled:true}")
public static class SolrHealthIndicatorConfiguration {
@Autowired
private HealthAggregator healthAggregator;
@Autowired
private Map<String, SolrServer> solrServers;
@Bean
@ConditionalOnMissingBean(name = "solrHealthIndicator")
public HealthIndicator rabbitHealthIndicator() {
if (this.solrServers.size() == 1) {
return new SolrHealthIndicator(this.solrServers.entrySet().iterator()
.next().getValue());
}
CompositeHealthIndicator composite = new CompositeHealthIndicator(
this.healthAggregator);
for (Map.Entry<String, SolrServer> entry : this.solrServers.entrySet()) {
composite.addHealthIndicator(entry.getKey(), new SolrHealthIndicator(
entry.getValue()));
}
return composite;
}
}
} }

@ -0,0 +1,47 @@
/*
* Copyright 2012-2014 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.health;
import org.apache.solr.client.solrj.SolrServer;
/**
* {@link HealthIndicator} for Apache Solr
*
* @author Andy Wilkinson
* @since 1.1.0
*/
public class SolrHealthIndicator implements HealthIndicator {
private final SolrServer solrServer;
public SolrHealthIndicator(SolrServer solrServer) {
this.solrServer = solrServer;
}
@Override
public Health health() {
Health health = new Health();
try {
this.solrServer.ping();
return health.up().withDetail("solrStatus",
this.solrServer.ping().getResponse().get("status"));
}
catch (Exception e) {
return health.down().withException(e);
}
}
}

@ -26,12 +26,14 @@ import org.springframework.boot.actuate.health.MongoHealthIndicator;
import org.springframework.boot.actuate.health.RabbitHealthIndicator; import org.springframework.boot.actuate.health.RabbitHealthIndicator;
import org.springframework.boot.actuate.health.RedisHealthIndicator; import org.springframework.boot.actuate.health.RedisHealthIndicator;
import org.springframework.boot.actuate.health.SimpleDataSourceHealthIndicator; import org.springframework.boot.actuate.health.SimpleDataSourceHealthIndicator;
import org.springframework.boot.actuate.health.SolrHealthIndicator;
import org.springframework.boot.actuate.health.VanillaHealthIndicator; import org.springframework.boot.actuate.health.VanillaHealthIndicator;
import org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration; import org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.EmbeddedDataSourceConfiguration; import org.springframework.boot.autoconfigure.jdbc.EmbeddedDataSourceConfiguration;
import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration; import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration;
import org.springframework.boot.autoconfigure.mongo.MongoDataAutoConfiguration; import org.springframework.boot.autoconfigure.mongo.MongoDataAutoConfiguration;
import org.springframework.boot.autoconfigure.redis.RedisAutoConfiguration; import org.springframework.boot.autoconfigure.redis.RedisAutoConfiguration;
import org.springframework.boot.autoconfigure.solr.SolrAutoConfiguration;
import org.springframework.boot.test.EnvironmentTestUtils; import org.springframework.boot.test.EnvironmentTestUtils;
import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext;
@ -39,7 +41,7 @@ import static org.junit.Assert.assertEquals;
/** /**
* Tests for {@link HealthIndicatorAutoConfiguration}. * Tests for {@link HealthIndicatorAutoConfiguration}.
* *
* @author Christian Dupuis * @author Christian Dupuis
*/ */
public class HealthIndicatorAutoConfigurationTests { public class HealthIndicatorAutoConfigurationTests {
@ -130,11 +132,12 @@ public class HealthIndicatorAutoConfigurationTests {
public void combinedHealthIndicator() { public void combinedHealthIndicator() {
this.context = new AnnotationConfigApplicationContext(); this.context = new AnnotationConfigApplicationContext();
this.context.register(MongoAutoConfiguration.class, RedisAutoConfiguration.class, this.context.register(MongoAutoConfiguration.class, RedisAutoConfiguration.class,
MongoDataAutoConfiguration.class, HealthIndicatorAutoConfiguration.class); MongoDataAutoConfiguration.class, SolrAutoConfiguration.class,
HealthIndicatorAutoConfiguration.class);
this.context.refresh(); this.context.refresh();
Map<String, HealthIndicator> beans = this.context Map<String, HealthIndicator> beans = this.context
.getBeansOfType(HealthIndicator.class); .getBeansOfType(HealthIndicator.class);
assertEquals(2, beans.size()); assertEquals(3, beans.size());
} }
@Test @Test
@ -190,4 +193,31 @@ public class HealthIndicatorAutoConfigurationTests {
assertEquals(VanillaHealthIndicator.class, beans.values().iterator().next() assertEquals(VanillaHealthIndicator.class, beans.values().iterator().next()
.getClass()); .getClass());
} }
@Test
public void solrHeathIndicator() {
this.context = new AnnotationConfigApplicationContext();
this.context.register(SolrAutoConfiguration.class,
HealthIndicatorAutoConfiguration.class);
this.context.refresh();
Map<String, HealthIndicator> beans = this.context
.getBeansOfType(HealthIndicator.class);
assertEquals(1, beans.size());
assertEquals(SolrHealthIndicator.class, beans.values().iterator().next()
.getClass());
}
@Test
public void notSolrHeathIndicator() {
this.context = new AnnotationConfigApplicationContext();
this.context.register(SolrAutoConfiguration.class,
HealthIndicatorAutoConfiguration.class);
EnvironmentTestUtils.addEnvironment(this.context, "health.solr.enabled:false");
this.context.refresh();
Map<String, HealthIndicator> beans = this.context
.getBeansOfType(HealthIndicator.class);
assertEquals(1, beans.size());
assertEquals(VanillaHealthIndicator.class, beans.values().iterator().next()
.getClass());
}
} }

@ -0,0 +1,91 @@
/*
* Copyright 2012-2014 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.health;
import java.io.IOException;
import org.apache.solr.client.solrj.SolrServer;
import org.apache.solr.client.solrj.response.SolrPingResponse;
import org.apache.solr.common.util.NamedList;
import org.junit.After;
import org.junit.Test;
import org.springframework.boot.actuate.autoconfigure.EndpointAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.HealthIndicatorAutoConfiguration;
import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration;
import org.springframework.boot.autoconfigure.solr.SolrAutoConfiguration;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
/**
* Tests for {@link SolrHealthIndicator}
*
* @author Andy Wilkinson
*/
public class SolrHealthIndicatorTests {
private AnnotationConfigApplicationContext context;
@After
public void close() {
if (this.context != null) {
this.context.close();
}
}
@Test
public void indicatorExists() {
this.context = new AnnotationConfigApplicationContext(
PropertyPlaceholderAutoConfiguration.class, SolrAutoConfiguration.class,
EndpointAutoConfiguration.class, HealthIndicatorAutoConfiguration.class);
assertEquals(1, this.context.getBeanNamesForType(SolrServer.class).length);
SolrHealthIndicator healthIndicator = this.context
.getBean(SolrHealthIndicator.class);
assertNotNull(healthIndicator);
}
@Test
public void solrIsUp() throws Exception {
SolrServer solrServer = mock(SolrServer.class);
SolrPingResponse pingResponse = new SolrPingResponse();
NamedList<Object> response = new NamedList<Object>();
response.add("status", "OK");
pingResponse.setResponse(response);
when(solrServer.ping()).thenReturn(pingResponse);
SolrHealthIndicator healthIndicator = new SolrHealthIndicator(solrServer);
Health health = healthIndicator.health();
assertEquals(Status.UP, health.getStatus());
assertEquals("OK", health.getDetails().get("solrStatus"));
}
@Test
public void solrIsDown() throws Exception {
SolrServer solrServer = mock(SolrServer.class);
when(solrServer.ping()).thenThrow(new IOException("Connection failed"));
SolrHealthIndicator healthIndicator = new SolrHealthIndicator(solrServer);
Health health = healthIndicator.health();
assertEquals(Status.DOWN, health.getStatus());
assertTrue(((String) health.getDetails().get("error"))
.contains("Connection failed"));
}
}
Loading…
Cancel
Save