diff --git a/spring-boot-actuator/pom.xml b/spring-boot-actuator/pom.xml index 508e125c14..e58f54bded 100644 --- a/spring-boot-actuator/pom.xml +++ b/spring-boot-actuator/pom.xml @@ -96,6 +96,11 @@ spring-data-solr true + + org.springframework.data + spring-data-elasticsearch + true + org.springframework.security spring-security-web diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/ElasticsearchHealthIndicatorConfiguration.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/ElasticsearchHealthIndicatorConfiguration.java new file mode 100644 index 0000000000..2f934bf3dd --- /dev/null +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/ElasticsearchHealthIndicatorConfiguration.java @@ -0,0 +1,55 @@ +/* + * Copyright 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.autoconfigure; + +import org.elasticsearch.client.Client; +import org.springframework.boot.actuate.health.ElasticsearchHealthIndicator; +import org.springframework.boot.actuate.health.ElasticsearchHealthIndicatorProperties; +import org.springframework.boot.actuate.health.HealthIndicator; +import org.springframework.boot.autoconfigure.AutoConfigureAfter; +import org.springframework.boot.autoconfigure.AutoConfigureBefore; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration Auto-configuration} for + * {@link org.springframework.boot.actuate.health.ElasticsearchHealthIndicator}. + * + * @author Binwei Yang + * @since 1.2.2 + */ +@Configuration +@AutoConfigureBefore({EndpointAutoConfiguration.class}) +@AutoConfigureAfter({HealthIndicatorAutoConfiguration.class}) +@ConditionalOnProperty(prefix = "management.health.elasticsearch", name = "enabled", matchIfMissing = true) +public class ElasticsearchHealthIndicatorConfiguration { + + @Bean + @ConditionalOnBean(Client.class) + @ConditionalOnMissingBean(name = "elasticsearchHealthIndicator") + public HealthIndicator elasticsearchHealthIndicator() { + return new ElasticsearchHealthIndicator(); + } + + @Bean + public ElasticsearchHealthIndicatorProperties elasticsearchHealthIndicatorProperties() { + return new ElasticsearchHealthIndicatorProperties(); + } +} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/ElasticsearchHealthIndicator.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/ElasticsearchHealthIndicator.java new file mode 100644 index 0000000000..9c062bbab0 --- /dev/null +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/ElasticsearchHealthIndicator.java @@ -0,0 +1,62 @@ +/* + * Copyright 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.elasticsearch.action.admin.cluster.health.ClusterHealthResponse; +import org.elasticsearch.client.Client; +import org.elasticsearch.client.Requests; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * Simple implementation of a {@link HealthIndicator} returning health status information for + * ElasticSearch cluster. + * + * @author Binwei Yang + * @since 1.2.2 + */ +public class ElasticsearchHealthIndicator extends ApplicationHealthIndicator { + @Autowired + private Client client; + + @Autowired + private ElasticsearchHealthIndicatorProperties properties; + + @Override + protected void doHealthCheck(Health.Builder builder) throws Exception { + try { + ClusterHealthResponse response = client.admin().cluster().health(Requests.clusterHealthRequest( + properties.getIndexNamesAsArray() + )).actionGet(100); + + switch (response.getStatus()) { + case GREEN: + builder.up(); + break; + case RED: + builder.down(); + break; + case YELLOW: + default: + builder.unknown(); + break; + } + builder.withDetail("clusterHealth", response); + } catch (Exception handled) { + builder.unknown().withDetail("exception", handled); + } + } +} diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/ElasticsearchHealthIndicatorProperties.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/ElasticsearchHealthIndicatorProperties.java new file mode 100644 index 0000000000..c0b10aa46a --- /dev/null +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/ElasticsearchHealthIndicatorProperties.java @@ -0,0 +1,52 @@ +/* + * Copyright 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.springframework.boot.context.properties.ConfigurationProperties; + +/** + * External configuration properties for {@link ElasticsearchHealthIndicator} + * + * @author Binwei Yang + * @since 1.2.2 + */ +@ConfigurationProperties("management.health.elasticsearch") +public class ElasticsearchHealthIndicatorProperties { + + public static final String ALL = "_all"; + + /** + * comma separated index names. the default includes all indices. + */ + private String indices = ALL; + + public String getIndices() { + return indices; + } + + public void setIndices(String indices) { + this.indices = indices; + } + + String[] getIndexNamesAsArray() { + if (null == indices) { + return new String[]{ALL}; + } else { + return indices.split(","); + } + } +} diff --git a/spring-boot-actuator/src/main/resources/META-INF/spring.factories b/spring-boot-actuator/src/main/resources/META-INF/spring.factories index 799422da3c..52b28beda8 100644 --- a/spring-boot-actuator/src/main/resources/META-INF/spring.factories +++ b/spring-boot-actuator/src/main/resources/META-INF/spring.factories @@ -12,4 +12,5 @@ org.springframework.boot.actuate.autoconfigure.MetricFilterAutoConfiguration,\ org.springframework.boot.actuate.autoconfigure.MetricRepositoryAutoConfiguration,\ org.springframework.boot.actuate.autoconfigure.PublicMetricsAutoConfiguration,\ org.springframework.boot.actuate.autoconfigure.TraceRepositoryAutoConfiguration,\ -org.springframework.boot.actuate.autoconfigure.TraceWebFilterAutoConfiguration +org.springframework.boot.actuate.autoconfigure.TraceWebFilterAutoConfiguration,\ +org.springframework.boot.actuate.autoconfigure.ElasticsearchHealthIndicatorConfiguration diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/ElasticsearchHealthIndicatorTest.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/ElasticsearchHealthIndicatorTest.java new file mode 100644 index 0000000000..2f59537f89 --- /dev/null +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/ElasticsearchHealthIndicatorTest.java @@ -0,0 +1,84 @@ +/* + * Copyright 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.elasticsearch.client.Client; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.springframework.boot.actuate.autoconfigure.ElasticsearchHealthIndicatorConfiguration; +import org.springframework.boot.actuate.autoconfigure.EndpointAutoConfiguration; +import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration; +import org.springframework.boot.autoconfigure.elasticsearch.ElasticsearchAutoConfiguration; +import org.springframework.boot.autoconfigure.elasticsearch.ElasticsearchDataAutoConfiguration; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +/** + * Test for {@link ElasticsearchHealthIndicator} for ElasticSearch cluster. + * + * @author Binwei Yang + * @since 1.2.2 + */ +public class ElasticsearchHealthIndicatorTest { + private AnnotationConfigApplicationContext context; + + @Before + public void setUp() throws Exception { + this.context = new AnnotationConfigApplicationContext( + PropertyPlaceholderAutoConfiguration.class, + ElasticsearchAutoConfiguration.class, + ElasticsearchDataAutoConfiguration.class, + EndpointAutoConfiguration.class, + ElasticsearchHealthIndicatorConfiguration.class + ); + } + + @After + public void close() { + if (null != context) { + context.close(); + } + } + + @Test + public void indicatorExists() { + assertEquals(1, this.context.getBeanNamesForType(Client.class).length); + + ElasticsearchHealthIndicator healthIndicator = this.context.getBean(ElasticsearchHealthIndicator.class); + assertNotNull(healthIndicator); + } + + @Test + public void configPropertiesUsed() { + ElasticsearchHealthIndicatorProperties properties = this.context.getBean(ElasticsearchHealthIndicatorProperties.class); + + // test default index + assertEquals(ElasticsearchHealthIndicatorProperties.ALL, properties.getIndices()); + assertEquals(1, properties.getIndexNamesAsArray().length); + assertEquals(ElasticsearchHealthIndicatorProperties.ALL, properties.getIndexNamesAsArray()[0]); + + // test specific indices + properties.setIndices("no-such-index"); + + ElasticsearchHealthIndicator healthIndicator = this.context.getBean(ElasticsearchHealthIndicator.class); + Health health = healthIndicator.health(); + assertEquals(Status.UNKNOWN, health.getStatus()); + } +}