mirror of
https://github.com/spring-projects/spring-boot.git
synced 2024-09-03 04:26:12 +08:00
Make Health and Status immutable
Update Health and Status objects to be immutable, update the existing builder methods to return new instances and add static convenience methods to Health.
This commit is contained in:
parent
660d9e24dc
commit
aa03d9a41c
@ -17,6 +17,7 @@
|
||||
package org.springframework.boot.actuate.health;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@ -31,21 +32,21 @@ public abstract class AbstractHealthAggregator implements HealthAggregator {
|
||||
|
||||
@Override
|
||||
public final Health aggregate(Map<String, Health> healths) {
|
||||
Health health = new Health();
|
||||
List<Status> status = new ArrayList<Status>();
|
||||
List<Status> statusCandidates = new ArrayList<Status>();
|
||||
Map<String, Object> details = new LinkedHashMap<String, Object>();
|
||||
for (Map.Entry<String, Health> entry : healths.entrySet()) {
|
||||
health.withDetail(entry.getKey(), entry.getValue());
|
||||
status.add(entry.getValue().getStatus());
|
||||
details.put(entry.getKey(), entry.getValue());
|
||||
statusCandidates.add(entry.getValue().getStatus());
|
||||
}
|
||||
health.status(aggregateStatus(status));
|
||||
return health;
|
||||
return new Health(aggregateStatus(statusCandidates), details);
|
||||
}
|
||||
|
||||
/**
|
||||
* Actual aggregation logic.
|
||||
* @param status list of given {@link Status} instances to aggregate
|
||||
* @return aggregated {@link Status}
|
||||
* Return the single 'aggregate' status that should be used from the specified
|
||||
* candidates.
|
||||
* @param candidates
|
||||
* @return a single status
|
||||
*/
|
||||
protected abstract Status aggregateStatus(List<Status> status);
|
||||
protected abstract Status aggregateStatus(List<Status> candidates);
|
||||
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ package org.springframework.boot.actuate.health;
|
||||
* {@link Health} instance and error handling.
|
||||
* <p>
|
||||
* This implementation is only suitable if an {@link Exception} raised from
|
||||
* {@link #doHealthCheck(Health)} should create a {@link Status#DOWN} health status.
|
||||
* {@link #doHealthCheck()} should create a {@link Status#DOWN} health status.
|
||||
*
|
||||
* @author Christian Dupuis
|
||||
* @since 1.1.0
|
||||
@ -30,21 +30,19 @@ public abstract class AbstractHealthIndicator implements HealthIndicator {
|
||||
|
||||
@Override
|
||||
public final Health health() {
|
||||
Health health = new Health();
|
||||
try {
|
||||
doHealthCheck(health);
|
||||
return doHealthCheck();
|
||||
}
|
||||
catch (Exception ex) {
|
||||
health.down().withException(ex);
|
||||
return Health.down(ex);
|
||||
}
|
||||
return health;
|
||||
}
|
||||
|
||||
/**
|
||||
* Actual health check logic.
|
||||
* @param health {@link Health} instance of report status.
|
||||
* @return the {@link Health}
|
||||
* @throws Exception any {@link Exception} that should create a {@link Status#DOWN}
|
||||
* system status.
|
||||
*/
|
||||
protected abstract void doHealthCheck(Health health) throws Exception;
|
||||
protected abstract Health doHealthCheck() throws Exception;
|
||||
}
|
||||
|
@ -16,11 +16,11 @@
|
||||
|
||||
package org.springframework.boot.actuate.health;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonAnyGetter;
|
||||
import com.fasterxml.jackson.annotation.JsonAnySetter;
|
||||
@ -29,8 +29,7 @@ import com.fasterxml.jackson.annotation.JsonInclude.Include;
|
||||
import com.fasterxml.jackson.annotation.JsonUnwrapped;
|
||||
|
||||
/**
|
||||
* Value object used to carry information about the health information of a component or
|
||||
* subsystem.
|
||||
* Carries information about the health of a component or subsystem.
|
||||
* <p>
|
||||
* {@link Health} contains a {@link Status} to express the state of a component or
|
||||
* subsystem and some additional details to carry some contextual information.
|
||||
@ -39,68 +38,52 @@ import com.fasterxml.jackson.annotation.JsonUnwrapped;
|
||||
* in a {@link HealthIndicator} would be:
|
||||
*
|
||||
* <pre class="code">
|
||||
* Health health = new Health();
|
||||
* try {
|
||||
* // do some test to determine state of component
|
||||
* health.up().withDetail("version", "1.1.2");
|
||||
* return Health.up("version", "1.1.2");
|
||||
* }
|
||||
* catch (Exception ex) {
|
||||
* health.down().withException(ex);
|
||||
* return Health.down(ex);
|
||||
* }
|
||||
* return health;
|
||||
* </pre>
|
||||
*
|
||||
* @author Christian Dupuis
|
||||
* @author Phillip Webb
|
||||
* @since 1.1.0
|
||||
*/
|
||||
@JsonInclude(Include.NON_EMPTY)
|
||||
public class Health {
|
||||
public final class Health {
|
||||
|
||||
private Status status;
|
||||
private static final Map<String, Object> NO_DETAILS = Collections
|
||||
.<String, Object> emptyMap();
|
||||
|
||||
private Map<String, Object> details;
|
||||
private final Status status;
|
||||
|
||||
public Health() {
|
||||
this(Status.UNKNOWN);
|
||||
}
|
||||
private final Map<String, Object> details;
|
||||
|
||||
public Health(Status status) {
|
||||
this.status = status;
|
||||
this.details = new LinkedHashMap<String, Object>();
|
||||
}
|
||||
|
||||
public Health status(Status status) {
|
||||
/**
|
||||
* Create a new {@link Health} instance with the specified status and details.
|
||||
* @param status the status
|
||||
* @param details the details or {@code null}
|
||||
*/
|
||||
public Health(Status status, Map<String, ?> details) {
|
||||
Assert.notNull(status, "Status must not be null");
|
||||
this.status = status;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Health up() {
|
||||
return status(Status.UP);
|
||||
}
|
||||
|
||||
public Health down() {
|
||||
return status(Status.DOWN);
|
||||
}
|
||||
|
||||
public Health withException(Exception ex) {
|
||||
Assert.notNull(ex, "Exception must not be null");
|
||||
return withDetail("error", ex.getClass().getName() + ": " + ex.getMessage());
|
||||
}
|
||||
|
||||
@JsonAnySetter
|
||||
public Health withDetail(String key, Object data) {
|
||||
Assert.notNull(key, "Key must not be null");
|
||||
Assert.notNull(data, "Data must not be null");
|
||||
this.details.put(key, data);
|
||||
return this;
|
||||
this.details = Collections.unmodifiableMap(details == null ? NO_DETAILS
|
||||
: new LinkedHashMap<String, Object>(details));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the status of the health (never {@code null})
|
||||
*/
|
||||
@JsonUnwrapped
|
||||
public Status getStatus() {
|
||||
return this.status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the details of the health or an empty map.
|
||||
*/
|
||||
@JsonAnyGetter
|
||||
public Map<String, Object> getDetails() {
|
||||
return this.details;
|
||||
@ -112,19 +95,105 @@ public class Health {
|
||||
return true;
|
||||
}
|
||||
if (obj != null && obj instanceof Health) {
|
||||
return ObjectUtils.nullSafeEquals(this.status, ((Health) obj).status)
|
||||
&& ObjectUtils.nullSafeEquals(this.details, ((Health) obj).details);
|
||||
Health other = (Health) obj;
|
||||
return this.status.equals(other.status) && this.details.equals(other.details);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hashCode = 0;
|
||||
if (this.status != null) {
|
||||
hashCode = this.status.hashCode();
|
||||
}
|
||||
int hashCode = this.status.hashCode();
|
||||
return 13 * hashCode + this.details.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getStatus() + " " + getDetails();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link Health} object from this one, containing an additional
|
||||
* exception detail.
|
||||
* @param ex the exception
|
||||
* @return a new {@link Health} instance
|
||||
*/
|
||||
public Health withException(Exception ex) {
|
||||
Assert.notNull(ex, "Exception must not be null");
|
||||
return withDetail("error", ex.getClass().getName() + ": " + ex.getMessage());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link Health} object from this one, containing an additional detail.
|
||||
* @param key the detail key
|
||||
* @param data the detail data
|
||||
* @return a new {@link Health} instance
|
||||
*/
|
||||
@JsonAnySetter
|
||||
public Health withDetail(String key, Object data) {
|
||||
Assert.notNull(key, "Key must not be null");
|
||||
Assert.notNull(data, "Data must not be null");
|
||||
Map<String, Object> details = new LinkedHashMap<String, Object>(this.details);
|
||||
details.put(key, data);
|
||||
return new Health(this.status, details);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link Health} instance with an {@link Status#UNKNOWN} status.
|
||||
* @return a new {@link Health} instance
|
||||
*/
|
||||
public static Health unknown() {
|
||||
return status(Status.UNKNOWN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link Health} instance with an {@link Status#UP} status.
|
||||
* @return a new {@link Health} instance
|
||||
*/
|
||||
public static Health up() {
|
||||
return status(Status.UP);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link Health} instance with an {@link Status#DOWN} status an the
|
||||
* specified exception details.
|
||||
* @param ex the exception
|
||||
* @return a new {@link Health} instance
|
||||
*/
|
||||
public static Health down(Exception ex) {
|
||||
return down().withException(ex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link Health} instance with a {@link Status#DOWN} status.
|
||||
* @return a new {@link Health} instance
|
||||
*/
|
||||
public static Health down() {
|
||||
return status(Status.DOWN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link Health} instance with an {@link Status#OUT_OF_SERVICE} status.
|
||||
* @return a new {@link Health} instance
|
||||
*/
|
||||
public static Health outOfService() {
|
||||
return status(Status.OUT_OF_SERVICE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link Health} instance with a specific status code.
|
||||
* @return a new {@link Health} instance
|
||||
*/
|
||||
public static Health status(String statusCode) {
|
||||
return status(new Status(statusCode));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link Health} instance with a specific {@link Status}.
|
||||
* @return a new {@link Health} instance
|
||||
*/
|
||||
public static Health status(Status status) {
|
||||
return new Health(status, null);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -38,9 +38,9 @@ public class MongoHealthIndicator extends AbstractHealthIndicator {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doHealthCheck(Health health) throws Exception {
|
||||
protected Health doHealthCheck() throws Exception {
|
||||
CommandResult result = this.mongoTemplate.executeCommand("{ serverStatus: 1 }");
|
||||
health.up().withDetail("version", result.getString("version"));
|
||||
return Health.up().withDetail("version", result.getString("version"));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -66,14 +66,14 @@ public class OrderedHealthAggregator extends AbstractHealthAggregator {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Status aggregateStatus(List<Status> status) {
|
||||
protected Status aggregateStatus(List<Status> candidates) {
|
||||
// If no status is given return UNKNOWN
|
||||
if (status.size() == 0) {
|
||||
if (candidates.size() == 0) {
|
||||
return Status.UNKNOWN;
|
||||
}
|
||||
// Sort given Status instances by configured order
|
||||
Collections.sort(status, new StatusComparator(this.statusOrder));
|
||||
return status.get(0);
|
||||
Collections.sort(candidates, new StatusComparator(this.statusOrder));
|
||||
return candidates.get(0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -41,17 +41,19 @@ public class RabbitHealthIndicator extends AbstractHealthIndicator {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doHealthCheck(Health health) throws Exception {
|
||||
health.up().withDetail("version",
|
||||
this.rabbitTemplate.execute(new ChannelCallback<String>() {
|
||||
protected Health doHealthCheck() throws Exception {
|
||||
return Health.up().withDetail("version", getVersion());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String doInRabbit(Channel channel) throws Exception {
|
||||
Map<String, Object> serverProperties = channel.getConnection()
|
||||
.getServerProperties();
|
||||
return serverProperties.get("version").toString();
|
||||
}
|
||||
}));
|
||||
private String getVersion() {
|
||||
return this.rabbitTemplate.execute(new ChannelCallback<String>() {
|
||||
@Override
|
||||
public String doInRabbit(Channel channel) throws Exception {
|
||||
Map<String, Object> serverProperties = channel.getConnection()
|
||||
.getServerProperties();
|
||||
return serverProperties.get("version").toString();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -40,12 +40,12 @@ public class RedisHealthIndicator extends AbstractHealthIndicator {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doHealthCheck(Health health) throws Exception {
|
||||
RedisConnection connection = null;
|
||||
protected Health doHealthCheck() throws Exception {
|
||||
RedisConnection connection = RedisConnectionUtils
|
||||
.getConnection(this.redisConnectionFactory);
|
||||
try {
|
||||
connection = RedisConnectionUtils.getConnection(this.redisConnectionFactory);
|
||||
Properties info = connection.info();
|
||||
health.up().withDetail("version", info.getProperty("redis_version"));
|
||||
return Health.up().withDetail("version", info.getProperty("redis_version"));
|
||||
}
|
||||
finally {
|
||||
RedisConnectionUtils.releaseConnection(connection,
|
||||
|
@ -35,7 +35,7 @@ import org.springframework.util.StringUtils;
|
||||
* @author Dave Syer
|
||||
* @author Christian Dupuis
|
||||
*/
|
||||
public class SimpleDataSourceHealthIndicator implements HealthIndicator {
|
||||
public class SimpleDataSourceHealthIndicator extends AbstractHealthIndicator {
|
||||
|
||||
private DataSource dataSource;
|
||||
|
||||
@ -63,7 +63,6 @@ public class SimpleDataSourceHealthIndicator implements HealthIndicator {
|
||||
/**
|
||||
* Create a new {@link SimpleDataSourceHealthIndicator} using the specified
|
||||
* datasource.
|
||||
*
|
||||
* @param dataSource the data source
|
||||
*/
|
||||
public SimpleDataSourceHealthIndicator(DataSource dataSource) {
|
||||
@ -72,40 +71,39 @@ public class SimpleDataSourceHealthIndicator implements HealthIndicator {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Health health() {
|
||||
Health health = new Health();
|
||||
health.up();
|
||||
protected Health doHealthCheck() throws Exception {
|
||||
if (this.dataSource == null) {
|
||||
return Health.up().withDetail("database", "unknown");
|
||||
}
|
||||
return doDataSourceHealthCheck();
|
||||
}
|
||||
|
||||
String product = "unknown";
|
||||
if (this.dataSource != null) {
|
||||
private Health doDataSourceHealthCheck() throws Exception {
|
||||
String product = getProduct();
|
||||
Health health = Health.up().withDetail("database", product);
|
||||
String query = detectQuery(product);
|
||||
if (StringUtils.hasText(query)) {
|
||||
try {
|
||||
product = this.jdbcTemplate.execute(new ConnectionCallback<String>() {
|
||||
|
||||
@Override
|
||||
public String doInConnection(Connection connection)
|
||||
throws SQLException, DataAccessException {
|
||||
return connection.getMetaData().getDatabaseProductName();
|
||||
}
|
||||
});
|
||||
health.withDetail("database", product);
|
||||
health = health.withDetail("hello",
|
||||
this.jdbcTemplate.queryForObject(query, Object.class));
|
||||
}
|
||||
catch (DataAccessException ex) {
|
||||
health.down().withException(ex);
|
||||
}
|
||||
String query = detectQuery(product);
|
||||
if (StringUtils.hasText(query)) {
|
||||
try {
|
||||
health.withDetail("hello",
|
||||
this.jdbcTemplate.queryForObject(query, Object.class));
|
||||
}
|
||||
catch (Exception ex) {
|
||||
health.down().withException(ex);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
return Health.down().withDetail("database", product).withException(ex);
|
||||
}
|
||||
}
|
||||
return health;
|
||||
}
|
||||
|
||||
private String getProduct() {
|
||||
return this.jdbcTemplate.execute(new ConnectionCallback<String>() {
|
||||
@Override
|
||||
public String doInConnection(Connection connection) throws SQLException,
|
||||
DataAccessException {
|
||||
return connection.getMetaData().getDatabaseProductName();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected String detectQuery(String product) {
|
||||
String query = this.query;
|
||||
if (!StringUtils.hasText(query)) {
|
||||
|
@ -20,7 +20,7 @@ import org.apache.solr.client.solrj.SolrServer;
|
||||
|
||||
/**
|
||||
* {@link HealthIndicator} for Apache Solr
|
||||
*
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
* @since 1.1.0
|
||||
*/
|
||||
@ -33,9 +33,9 @@ public class SolrHealthIndicator extends AbstractHealthIndicator {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doHealthCheck(Health health) throws Exception {
|
||||
this.solrServer.ping();
|
||||
health.up().withDetail("solrStatus",
|
||||
this.solrServer.ping().getResponse().get("status"));
|
||||
protected Health doHealthCheck() throws Exception {
|
||||
Object status = this.solrServer.ping().getResponse().get("status");
|
||||
return Health.up().withDetail("solrStatus", status);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
* @since 1.1.0
|
||||
*/
|
||||
@JsonInclude(Include.NON_EMPTY)
|
||||
public class Status {
|
||||
public final class Status {
|
||||
|
||||
/**
|
||||
* Convenient constant value representing unknown state
|
||||
|
@ -25,8 +25,8 @@ package org.springframework.boot.actuate.health;
|
||||
public class VanillaHealthIndicator extends AbstractHealthIndicator {
|
||||
|
||||
@Override
|
||||
protected void doHealthCheck(Health health) throws Exception {
|
||||
health.up();
|
||||
protected Health doHealthCheck() throws Exception {
|
||||
return Health.up();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -65,7 +65,7 @@ public class HealthEndpointTests extends AbstractEndpointTests<HealthEndpoint> {
|
||||
|
||||
@Override
|
||||
public Health health() {
|
||||
return new Health().status(new Status("FINE"));
|
||||
return Health.status("FINE");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ public class HealthMvcEndpointTests {
|
||||
|
||||
@Test
|
||||
public void up() {
|
||||
when(this.endpoint.invoke()).thenReturn(new Health().up());
|
||||
when(this.endpoint.invoke()).thenReturn(Health.up());
|
||||
Object result = this.mvc.invoke();
|
||||
assertTrue(result instanceof Health);
|
||||
assertTrue(((Health) result).getStatus() == Status.UP);
|
||||
@ -60,7 +60,7 @@ public class HealthMvcEndpointTests {
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void down() {
|
||||
when(this.endpoint.invoke()).thenReturn(new Health().down());
|
||||
when(this.endpoint.invoke()).thenReturn(Health.down());
|
||||
Object result = this.mvc.invoke();
|
||||
assertTrue(result instanceof ResponseEntity);
|
||||
ResponseEntity<Health> response = (ResponseEntity<Health>) result;
|
||||
@ -71,7 +71,7 @@ public class HealthMvcEndpointTests {
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void customMapping() {
|
||||
when(this.endpoint.invoke()).thenReturn(new Health().status(new Status("OK")));
|
||||
when(this.endpoint.invoke()).thenReturn(Health.status("OK"));
|
||||
this.mvc.setStatusMapping(Collections.singletonMap("OK",
|
||||
HttpStatus.INTERNAL_SERVER_ERROR));
|
||||
Object result = this.mvc.invoke();
|
||||
|
@ -34,7 +34,7 @@ import static org.mockito.BDDMockito.given;
|
||||
|
||||
/**
|
||||
* Tests for {@link CompositeHealthIndicator}
|
||||
*
|
||||
*
|
||||
* @author Tyler J. Frederick
|
||||
* @author Phillip Webb
|
||||
* @author Christian Dupuis
|
||||
@ -55,9 +55,9 @@ public class CompositeHealthIndicatorTests {
|
||||
@Before
|
||||
public void setup() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
given(this.one.health()).willReturn(new Health().withDetail("1", "1"));
|
||||
given(this.two.health()).willReturn(new Health().withDetail("2", "2"));
|
||||
given(this.three.health()).willReturn(new Health().withDetail("3", "3"));
|
||||
given(this.one.health()).willReturn(Health.unknown().withDetail("1", "1"));
|
||||
given(this.two.health()).willReturn(Health.unknown().withDetail("2", "2"));
|
||||
given(this.three.health()).willReturn(Health.unknown().withDetail("3", "3"));
|
||||
|
||||
this.healthAggregator = new OrderedHealthAggregator();
|
||||
}
|
||||
@ -72,9 +72,9 @@ public class CompositeHealthIndicatorTests {
|
||||
Health result = composite.health();
|
||||
assertThat(result.getDetails().size(), equalTo(2));
|
||||
assertThat(result.getDetails(),
|
||||
hasEntry("one", (Object) new Health().withDetail("1", "1")));
|
||||
hasEntry("one", (Object) Health.unknown().withDetail("1", "1")));
|
||||
assertThat(result.getDetails(),
|
||||
hasEntry("two", (Object) new Health().withDetail("2", "2")));
|
||||
hasEntry("two", (Object) Health.unknown().withDetail("2", "2")));
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -88,11 +88,11 @@ public class CompositeHealthIndicatorTests {
|
||||
Health result = composite.health();
|
||||
assertThat(result.getDetails().size(), equalTo(3));
|
||||
assertThat(result.getDetails(),
|
||||
hasEntry("one", (Object) new Health().withDetail("1", "1")));
|
||||
hasEntry("one", (Object) Health.unknown().withDetail("1", "1")));
|
||||
assertThat(result.getDetails(),
|
||||
hasEntry("two", (Object) new Health().withDetail("2", "2")));
|
||||
hasEntry("two", (Object) Health.unknown().withDetail("2", "2")));
|
||||
assertThat(result.getDetails(),
|
||||
hasEntry("three", (Object) new Health().withDetail("3", "3")));
|
||||
hasEntry("three", (Object) Health.unknown().withDetail("3", "3")));
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -104,9 +104,9 @@ public class CompositeHealthIndicatorTests {
|
||||
Health result = composite.health();
|
||||
assertThat(result.getDetails().size(), equalTo(2));
|
||||
assertThat(result.getDetails(),
|
||||
hasEntry("one", (Object) new Health().withDetail("1", "1")));
|
||||
hasEntry("one", (Object) Health.unknown().withDetail("1", "1")));
|
||||
assertThat(result.getDetails(),
|
||||
hasEntry("two", (Object) new Health().withDetail("2", "2")));
|
||||
hasEntry("two", (Object) Health.unknown().withDetail("2", "2")));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -0,0 +1,156 @@
|
||||
/*
|
||||
* 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.util.Collections;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link Health}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class HealthTests {
|
||||
|
||||
@Rule
|
||||
public ExpectedException thrown = ExpectedException.none();
|
||||
|
||||
@Test
|
||||
public void statusMustNotBeNull() throws Exception {
|
||||
this.thrown.expect(IllegalArgumentException.class);
|
||||
this.thrown.expectMessage("Status must not be null");
|
||||
new Health(null, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createWithStatus() throws Exception {
|
||||
Health health = new Health(Status.UP, null);
|
||||
assertThat(health.getStatus(), equalTo(Status.UP));
|
||||
assertThat(health.getDetails().size(), equalTo(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createWithDetails() throws Exception {
|
||||
Health health = new Health(Status.UP, Collections.singletonMap("a", "b"));
|
||||
assertThat(health.getStatus(), equalTo(Status.UP));
|
||||
assertThat(health.getDetails().get("a"), equalTo((Object) "b"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equalsAndHashCode() throws Exception {
|
||||
Health h1 = new Health(Status.UP, Collections.singletonMap("a", "b"));
|
||||
Health h2 = new Health(Status.UP, Collections.singletonMap("a", "b"));
|
||||
Health h3 = new Health(Status.UP, null);
|
||||
assertThat(h1, equalTo(h1));
|
||||
assertThat(h1, equalTo(h2));
|
||||
assertThat(h1, not(equalTo(h3)));
|
||||
assertThat(h1.hashCode(), equalTo(h1.hashCode()));
|
||||
assertThat(h1.hashCode(), equalTo(h2.hashCode()));
|
||||
assertThat(h1.hashCode(), not(equalTo(h3.hashCode())));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void withException() throws Exception {
|
||||
RuntimeException ex = new RuntimeException("bang");
|
||||
Health health = new Health(Status.UP, Collections.singletonMap("a", "b"))
|
||||
.withException(ex);
|
||||
assertThat(health.getDetails().get("a"), equalTo((Object) "b"));
|
||||
assertThat(health.getDetails().get("error"),
|
||||
equalTo((Object) "java.lang.RuntimeException: bang"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void withDetails() throws Exception {
|
||||
Health health = new Health(Status.UP, Collections.singletonMap("a", "b"))
|
||||
.withDetail("c", "d");
|
||||
assertThat(health.getDetails().get("a"), equalTo((Object) "b"));
|
||||
assertThat(health.getDetails().get("c"), equalTo((Object) "d"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void unknownWithDetails() throws Exception {
|
||||
Health health = Health.unknown().withDetail("a", "b");
|
||||
assertThat(health.getStatus(), equalTo(Status.UNKNOWN));
|
||||
assertThat(health.getDetails().get("a"), equalTo((Object) "b"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void unknown() throws Exception {
|
||||
Health health = Health.unknown();
|
||||
assertThat(health.getStatus(), equalTo(Status.UNKNOWN));
|
||||
assertThat(health.getDetails().size(), equalTo(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void upWithDetails() throws Exception {
|
||||
Health health = Health.up().withDetail("a", "b");
|
||||
assertThat(health.getStatus(), equalTo(Status.UP));
|
||||
assertThat(health.getDetails().get("a"), equalTo((Object) "b"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void up() throws Exception {
|
||||
Health health = Health.up();
|
||||
assertThat(health.getStatus(), equalTo(Status.UP));
|
||||
assertThat(health.getDetails().size(), equalTo(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void downWithException() throws Exception {
|
||||
RuntimeException ex = new RuntimeException("bang");
|
||||
Health health = Health.down(ex);
|
||||
assertThat(health.getStatus(), equalTo(Status.DOWN));
|
||||
assertThat(health.getDetails().get("error"),
|
||||
equalTo((Object) "java.lang.RuntimeException: bang"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void down() throws Exception {
|
||||
Health health = Health.down();
|
||||
assertThat(health.getStatus(), equalTo(Status.DOWN));
|
||||
assertThat(health.getDetails().size(), equalTo(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void outOfService() throws Exception {
|
||||
Health health = Health.outOfService();
|
||||
assertThat(health.getStatus(), equalTo(Status.OUT_OF_SERVICE));
|
||||
assertThat(health.getDetails().size(), equalTo(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void statusCode() throws Exception {
|
||||
Health health = Health.status("UP");
|
||||
assertThat(health.getStatus(), equalTo(Status.UP));
|
||||
assertThat(health.getDetails().size(), equalTo(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void status() throws Exception {
|
||||
Health health = Health.status(Status.UP);
|
||||
assertThat(health.getStatus(), equalTo(Status.UP));
|
||||
assertThat(health.getDetails().size(), equalTo(0));
|
||||
}
|
||||
|
||||
}
|
@ -42,10 +42,10 @@ public class OrderedHealthAggregatorTests {
|
||||
@Test
|
||||
public void defaultOrder() {
|
||||
Map<String, Health> healths = new HashMap<String, Health>();
|
||||
healths.put("h1", new Health(Status.DOWN));
|
||||
healths.put("h2", new Health(Status.UP));
|
||||
healths.put("h3", new Health(Status.UNKNOWN));
|
||||
healths.put("h4", new Health(Status.OUT_OF_SERVICE));
|
||||
healths.put("h1", Health.status(Status.DOWN));
|
||||
healths.put("h2", Health.status(Status.UP));
|
||||
healths.put("h3", Health.status(Status.UNKNOWN));
|
||||
healths.put("h4", Health.status(Status.OUT_OF_SERVICE));
|
||||
assertEquals(Status.DOWN, this.healthAggregator.aggregate(healths).getStatus());
|
||||
}
|
||||
|
||||
@ -54,21 +54,21 @@ public class OrderedHealthAggregatorTests {
|
||||
this.healthAggregator.setStatusOrder(Status.UNKNOWN, Status.UP,
|
||||
Status.OUT_OF_SERVICE, Status.DOWN);
|
||||
Map<String, Health> healths = new HashMap<String, Health>();
|
||||
healths.put("h1", new Health(Status.DOWN));
|
||||
healths.put("h2", new Health(Status.UP));
|
||||
healths.put("h3", new Health(Status.UNKNOWN));
|
||||
healths.put("h4", new Health(Status.OUT_OF_SERVICE));
|
||||
healths.put("h1", Health.status(Status.DOWN));
|
||||
healths.put("h2", Health.status(Status.UP));
|
||||
healths.put("h3", Health.status(Status.UNKNOWN));
|
||||
healths.put("h4", Health.status(Status.OUT_OF_SERVICE));
|
||||
assertEquals(Status.UNKNOWN, this.healthAggregator.aggregate(healths).getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultOrderWithCustomStatus() {
|
||||
Map<String, Health> healths = new HashMap<String, Health>();
|
||||
healths.put("h1", new Health(Status.DOWN));
|
||||
healths.put("h2", new Health(Status.UP));
|
||||
healths.put("h3", new Health(Status.UNKNOWN));
|
||||
healths.put("h4", new Health(Status.OUT_OF_SERVICE));
|
||||
healths.put("h5", new Health(new Status("CUSTOM")));
|
||||
healths.put("h1", Health.status(Status.DOWN));
|
||||
healths.put("h2", Health.status(Status.UP));
|
||||
healths.put("h3", Health.status(Status.UNKNOWN));
|
||||
healths.put("h4", Health.status(Status.OUT_OF_SERVICE));
|
||||
healths.put("h5", Health.status(new Status("CUSTOM")));
|
||||
assertEquals(new Status("CUSTOM"), this.healthAggregator.aggregate(healths)
|
||||
.getStatus());
|
||||
}
|
||||
@ -78,11 +78,11 @@ public class OrderedHealthAggregatorTests {
|
||||
this.healthAggregator.setStatusOrder(Arrays.asList("DOWN", "OUT_OF_SERVICE",
|
||||
"UP", "UNKNOWN", "CUSTOM"));
|
||||
Map<String, Health> healths = new HashMap<String, Health>();
|
||||
healths.put("h1", new Health(Status.DOWN));
|
||||
healths.put("h2", new Health(Status.UP));
|
||||
healths.put("h3", new Health(Status.UNKNOWN));
|
||||
healths.put("h4", new Health(Status.OUT_OF_SERVICE));
|
||||
healths.put("h5", new Health(new Status("CUSTOM")));
|
||||
healths.put("h1", Health.status(Status.DOWN));
|
||||
healths.put("h2", Health.status(Status.UP));
|
||||
healths.put("h3", Health.status(Status.UNKNOWN));
|
||||
healths.put("h4", Health.status(Status.OUT_OF_SERVICE));
|
||||
healths.put("h5", Health.status(new Status("CUSTOM")));
|
||||
assertEquals(Status.DOWN, this.healthAggregator.aggregate(healths).getStatus());
|
||||
}
|
||||
|
||||
|
@ -27,8 +27,10 @@ import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.datasource.DriverManagerDataSource;
|
||||
import org.springframework.jdbc.datasource.SingleConnectionDataSource;
|
||||
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
@ -78,7 +80,7 @@ public class SimpleDataSourceHealthIndicatorTests {
|
||||
this.indicator.setDataSource(this.dataSource);
|
||||
this.indicator.setQuery("SELECT COUNT(*) from BAR");
|
||||
Health health = this.indicator.health();
|
||||
assertNotNull(health.getDetails().get("database"));
|
||||
assertThat(health.getDetails().get("database"), notNullValue());
|
||||
assertEquals(Status.DOWN, health.getStatus());
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user