Fix health status aggregation bug

pull/1780/head
Christian Dupuis 10 years ago
parent cebfd44d16
commit 6c66ff78c0

@ -18,7 +18,6 @@ package org.springframework.boot.actuate.autoconfigure;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.List;
import java.util.Map; import java.util.Map;
import javax.sql.DataSource; import javax.sql.DataSource;
@ -26,7 +25,6 @@ import javax.sql.DataSource;
import org.apache.solr.client.solrj.SolrServer; 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.boot.actuate.health.ApplicationHealthIndicator; import org.springframework.boot.actuate.health.ApplicationHealthIndicator;
import org.springframework.boot.actuate.health.CompositeHealthIndicator; import org.springframework.boot.actuate.health.CompositeHealthIndicator;
import org.springframework.boot.actuate.health.DataSourceHealthIndicator; import org.springframework.boot.actuate.health.DataSourceHealthIndicator;
@ -54,6 +52,7 @@ 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.autoconfigure.solr.SolrAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
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;
@ -72,17 +71,18 @@ import org.springframework.data.redis.connection.RedisConnectionFactory;
@AutoConfigureAfter({ DataSourceAutoConfiguration.class, MongoAutoConfiguration.class, @AutoConfigureAfter({ DataSourceAutoConfiguration.class, MongoAutoConfiguration.class,
MongoDataAutoConfiguration.class, RedisAutoConfiguration.class, MongoDataAutoConfiguration.class, RedisAutoConfiguration.class,
RabbitAutoConfiguration.class, SolrAutoConfiguration.class }) RabbitAutoConfiguration.class, SolrAutoConfiguration.class })
@EnableConfigurationProperties({ HealthIndicatorAutoConfigurationProperties.class })
public class HealthIndicatorAutoConfiguration { public class HealthIndicatorAutoConfiguration {
@Value("${health.status.order:}") @Autowired
private List<String> statusOrder = null; private HealthIndicatorAutoConfigurationProperties configurationProperties = new HealthIndicatorAutoConfigurationProperties();
@Bean @Bean
@ConditionalOnMissingBean @ConditionalOnMissingBean
public HealthAggregator healthAggregator() { public HealthAggregator healthAggregator() {
OrderedHealthAggregator healthAggregator = new OrderedHealthAggregator(); OrderedHealthAggregator healthAggregator = new OrderedHealthAggregator();
if (this.statusOrder != null) { if (this.configurationProperties.getOrder() != null) {
healthAggregator.setStatusOrder(this.statusOrder); healthAggregator.setStatusOrder(this.configurationProperties.getOrder());
} }
return healthAggregator; return healthAggregator;
} }

@ -0,0 +1,42 @@
/*
* 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.autoconfigure;
import java.util.List;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* Configuration properties for some health properties
* @author Christian Dupuis
*/
@ConfigurationProperties("health.status")
public class HealthIndicatorAutoConfigurationProperties {
private List<String> order = null;
public List<String> getOrder() {
return this.order;
}
public void setOrder(List<String> statusOrder) {
if (statusOrder != null && statusOrder.size() > 0) {
this.order = statusOrder;
}
}
}

@ -16,6 +16,7 @@
package org.springframework.boot.actuate.health; package org.springframework.boot.actuate.health;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
@ -67,13 +68,20 @@ public class OrderedHealthAggregator extends AbstractHealthAggregator {
@Override @Override
protected Status aggregateStatus(List<Status> candidates) { protected Status aggregateStatus(List<Status> candidates) {
// Only sort those status instances that we know about
List<Status> filteredCandidates = new ArrayList<Status>();
for (Status candidate : candidates) {
if (this.statusOrder.contains(candidate.getCode())) {
filteredCandidates.add(candidate);
}
}
// If no status is given return UNKNOWN // If no status is given return UNKNOWN
if (candidates.size() == 0) { if (filteredCandidates.size() == 0) {
return Status.UNKNOWN; return Status.UNKNOWN;
} }
// Sort given Status instances by configured order // Sort given Status instances by configured order
Collections.sort(candidates, new StatusComparator(this.statusOrder)); Collections.sort(filteredCandidates, new StatusComparator(this.statusOrder));
return candidates.get(0); return filteredCandidates.get(0);
} }
/** /**

@ -45,8 +45,8 @@ public class HealthEndpointTests extends AbstractEndpointTests<HealthEndpoint> {
@Test @Test
public void invoke() throws Exception { public void invoke() throws Exception {
Status result = new Status("FINE"); // As FINE isn't configured in the order we get UNKOWN
assertThat(getEndpointBean().invoke().getStatus(), equalTo(result)); assertThat(getEndpointBean().invoke().getStatus(), equalTo(Status.UNKNOWN));
} }
@Configuration @Configuration

@ -69,8 +69,7 @@ public class OrderedHealthAggregatorTests {
healths.put("h3", new Health.Builder().status(Status.UNKNOWN).build()); healths.put("h3", new Health.Builder().status(Status.UNKNOWN).build());
healths.put("h4", new Health.Builder().status(Status.OUT_OF_SERVICE).build()); healths.put("h4", new Health.Builder().status(Status.OUT_OF_SERVICE).build());
healths.put("h5", new Health.Builder().status(new Status("CUSTOM")).build()); healths.put("h5", new Health.Builder().status(new Status("CUSTOM")).build());
assertEquals(new Status("CUSTOM"), this.healthAggregator.aggregate(healths) assertEquals(Status.DOWN, this.healthAggregator.aggregate(healths).getStatus());
.getStatus());
} }
@Test @Test

Loading…
Cancel
Save