Fix health status aggregation bug

This commit is contained in:
Christian Dupuis 2014-10-28 12:46:14 +01:00
parent cebfd44d16
commit 6c66ff78c0
5 changed files with 62 additions and 13 deletions

View File

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

View File

@ -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;
}
}
}

View File

@ -16,6 +16,7 @@
package org.springframework.boot.actuate.health;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
@ -67,13 +68,20 @@ public class OrderedHealthAggregator extends AbstractHealthAggregator {
@Override
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 (candidates.size() == 0) {
if (filteredCandidates.size() == 0) {
return Status.UNKNOWN;
}
// Sort given Status instances by configured order
Collections.sort(candidates, new StatusComparator(this.statusOrder));
return candidates.get(0);
Collections.sort(filteredCandidates, new StatusComparator(this.statusOrder));
return filteredCandidates.get(0);
}
/**

View File

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

View File

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