Skip to content

Commit a9a57e5

Browse files
committed
1 parent 9cde736 commit a9a57e5

File tree

10 files changed

+219
-27
lines changed

10 files changed

+219
-27
lines changed

spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/health/HealthEndpointWebExtensionConfiguration.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,10 @@ class HealthEndpointWebExtensionConfiguration {
5151
@Bean
5252
@ConditionalOnMissingBean
5353
public HealthStatusHttpMapper createHealthStatusHttpMapper(
54-
HealthIndicatorProperties healthIndicatorProperties) {
54+
HealthIndicatorProperties properties) {
5555
HealthStatusHttpMapper statusHttpMapper = new HealthStatusHttpMapper();
56-
if (healthIndicatorProperties.getHttpMapping() != null) {
57-
statusHttpMapper.addStatusMapping(healthIndicatorProperties.getHttpMapping());
56+
if (properties.getStatus().getHttpMapping() != null) {
57+
statusHttpMapper.addStatusMapping(properties.getStatus().getHttpMapping());
5858
}
5959
return statusHttpMapper;
6060
}

spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/health/HealthIndicatorAutoConfiguration.java

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,15 @@
1616

1717
package org.springframework.boot.actuate.autoconfigure.health;
1818

19+
import java.util.LinkedHashMap;
1920
import java.util.Map;
21+
import java.util.function.Function;
2022

2123
import reactor.core.publisher.Flux;
2224

2325
import org.springframework.boot.actuate.health.ApplicationHealthIndicator;
26+
import org.springframework.boot.actuate.health.DefaultGroupHealthIndicator;
27+
import org.springframework.boot.actuate.health.DefaultGroupReactiveHealthIndicator;
2428
import org.springframework.boot.actuate.health.HealthAggregator;
2529
import org.springframework.boot.actuate.health.HealthIndicator;
2630
import org.springframework.boot.actuate.health.HealthIndicatorRegistry;
@@ -60,17 +64,24 @@ public ApplicationHealthIndicator applicationHealthIndicator() {
6064
public OrderedHealthAggregator healthAggregator(
6165
HealthIndicatorProperties properties) {
6266
OrderedHealthAggregator healthAggregator = new OrderedHealthAggregator();
63-
if (properties.getOrder() != null) {
64-
healthAggregator.setStatusOrder(properties.getOrder());
67+
if (properties.getStatus().getOrder() != null) {
68+
healthAggregator.setStatusOrder(properties.getStatus().getOrder());
6569
}
6670
return healthAggregator;
6771
}
6872

6973
@Bean
7074
@ConditionalOnMissingBean(HealthIndicatorRegistry.class)
7175
public HealthIndicatorRegistry healthIndicatorRegistry(
76+
HealthIndicatorProperties properties, HealthAggregator healthAggregator,
7277
ApplicationContext applicationContext) {
73-
return HealthIndicatorRegistryBeans.get(applicationContext);
78+
HealthIndicatorRegistry registry = HealthIndicatorRegistryBeans
79+
.get(applicationContext);
80+
extractGroups(properties, registry::get).forEach(
81+
(groupName, groupHealthIndicators) -> registry.register(groupName,
82+
new DefaultGroupHealthIndicator(healthAggregator,
83+
groupHealthIndicators)));
84+
return registry;
7485
}
7586

7687
@Configuration(proxyBeanMethods = false)
@@ -80,13 +91,41 @@ static class ReactiveHealthIndicatorConfiguration {
8091
@Bean
8192
@ConditionalOnMissingBean
8293
public ReactiveHealthIndicatorRegistry reactiveHealthIndicatorRegistry(
94+
HealthIndicatorProperties properties, HealthAggregator healthAggregator,
8395
Map<String, ReactiveHealthIndicator> reactiveHealthIndicators,
8496
Map<String, HealthIndicator> healthIndicators) {
85-
return new ReactiveHealthIndicatorRegistryFactory()
97+
ReactiveHealthIndicatorRegistry registry = new ReactiveHealthIndicatorRegistryFactory()
8698
.createReactiveHealthIndicatorRegistry(reactiveHealthIndicators,
8799
healthIndicators);
100+
extractGroups(properties, registry::get).forEach(
101+
(groupName, groupHealthIndicators) -> registry.register(groupName,
102+
new DefaultGroupReactiveHealthIndicator(healthAggregator,
103+
groupHealthIndicators)));
104+
return registry;
88105
}
89106

90107
}
91108

109+
private static <T> Map<String, Map<String, T>> extractGroups(
110+
HealthIndicatorProperties properties,
111+
Function<String, T> healthIndicatorByName) {
112+
Map<String, Map<String, T>> groupDefinitions = new LinkedHashMap<>();
113+
properties.getGroups().forEach((groupName, indicatorNames) -> {
114+
if (healthIndicatorByName.apply(groupName) != null) {
115+
throw new IllegalArgumentException(
116+
"Could not register health indicator group named '" + groupName
117+
+ "', an health indicator with that name is already registered");
118+
}
119+
Map<String, T> groupHealthIndicators = new LinkedHashMap<>();
120+
indicatorNames.forEach((name) -> {
121+
T healthIndicator = healthIndicatorByName.apply(name);
122+
if (healthIndicator != null) {
123+
groupHealthIndicators.put(name, healthIndicator);
124+
}
125+
});
126+
groupDefinitions.put(groupName, groupHealthIndicators);
127+
});
128+
return groupDefinitions;
129+
}
130+
92131
}

spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/health/HealthIndicatorProperties.java

Lines changed: 36 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -28,32 +28,52 @@
2828
* @author Christian Dupuis
2929
* @since 2.0.0
3030
*/
31-
@ConfigurationProperties(prefix = "management.health.status")
31+
@ConfigurationProperties(prefix = "management.health")
3232
public class HealthIndicatorProperties {
3333

3434
/**
35-
* Comma-separated list of health statuses in order of severity.
35+
* Health indicator groups. Each entry maps the name of a group with a list of health
36+
* indicators to associate with the group.
3637
*/
37-
private List<String> order = null;
38+
private final Map<String, List<String>> groups = new HashMap<>();
3839

39-
/**
40-
* Mapping of health statuses to HTTP status codes. By default, registered health
41-
* statuses map to sensible defaults (for example, UP maps to 200).
42-
*/
43-
private final Map<String, Integer> httpMapping = new HashMap<>();
40+
private final Status status = new Status();
4441

45-
public List<String> getOrder() {
46-
return this.order;
42+
public Map<String, List<String>> getGroups() {
43+
return this.groups;
4744
}
4845

49-
public void setOrder(List<String> statusOrder) {
50-
if (statusOrder != null && !statusOrder.isEmpty()) {
51-
this.order = statusOrder;
52-
}
46+
public Status getStatus() {
47+
return this.status;
5348
}
5449

55-
public Map<String, Integer> getHttpMapping() {
56-
return this.httpMapping;
50+
public static class Status {
51+
52+
/**
53+
* Comma-separated list of health statuses in order of severity.
54+
*/
55+
private List<String> order = null;
56+
57+
/**
58+
* Mapping of health statuses to HTTP status codes. By default, registered health
59+
* statuses map to sensible defaults (for example, UP maps to 200).
60+
*/
61+
private final Map<String, Integer> httpMapping = new HashMap<>();
62+
63+
public List<String> getOrder() {
64+
return this.order;
65+
}
66+
67+
public void setOrder(List<String> statusOrder) {
68+
if (statusOrder != null && !statusOrder.isEmpty()) {
69+
this.order = statusOrder;
70+
}
71+
}
72+
73+
public Map<String, Integer> getHttpMapping() {
74+
return this.httpMapping;
75+
}
76+
5777
}
5878

5979
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
* Copyright 2012-2019 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.actuate.health;
18+
19+
import java.util.Map;
20+
21+
/**
22+
* @author Stephane Nicoll
23+
*/
24+
public class DefaultGroupHealthIndicator extends CompositeHealthIndicator
25+
implements GroupHealthIndicator {
26+
27+
public DefaultGroupHealthIndicator(HealthAggregator healthAggregator,
28+
Map<String, HealthIndicator> indicators) {
29+
super(healthAggregator, indicators);
30+
}
31+
32+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
* Copyright 2012-2019 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.actuate.health;
18+
19+
import java.util.Map;
20+
21+
/**
22+
* @author Stephane Nicoll
23+
*/
24+
public class DefaultGroupReactiveHealthIndicator extends CompositeReactiveHealthIndicator
25+
implements GroupReactiveHealthIndicator {
26+
27+
public DefaultGroupReactiveHealthIndicator(HealthAggregator healthAggregator,
28+
Map<String, ReactiveHealthIndicator> healthIndicators) {
29+
super(healthAggregator,
30+
new DefaultReactiveHealthIndicatorRegistry(healthIndicators));
31+
}
32+
33+
}

spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/DefaultHealthIndicatorRegistry.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,13 @@ public HealthIndicator get(String name) {
8585
@Override
8686
public Map<String, HealthIndicator> getAll() {
8787
synchronized (this.monitor) {
88-
return Collections
89-
.unmodifiableMap(new LinkedHashMap<>(this.healthIndicators));
88+
Map<String, HealthIndicator> allIndicators = new LinkedHashMap<>();
89+
this.healthIndicators.forEach((name, indicator) -> {
90+
if (!(indicator instanceof GroupHealthIndicator)) {
91+
allIndicators.put(name, indicator);
92+
}
93+
});
94+
return Collections.unmodifiableMap(allIndicators);
9095
}
9196
}
9297

spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/DefaultReactiveHealthIndicatorRegistry.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,13 @@ public ReactiveHealthIndicator get(String name) {
8888
@Override
8989
public Map<String, ReactiveHealthIndicator> getAll() {
9090
synchronized (this.monitor) {
91-
return Collections
92-
.unmodifiableMap(new LinkedHashMap<>(this.healthIndicators));
91+
Map<String, ReactiveHealthIndicator> allIndicators = new LinkedHashMap<>();
92+
this.healthIndicators.forEach((name, indicator) -> {
93+
if (!(indicator instanceof GroupReactiveHealthIndicator)) {
94+
allIndicators.put(name, indicator);
95+
}
96+
});
97+
return Collections.unmodifiableMap(allIndicators);
9398
}
9499
}
95100

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/*
2+
* Copyright 2012-2019 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.actuate.health;
18+
19+
/**
20+
* @author Stephane Nicoll
21+
* @since 2.2.0
22+
*/
23+
public interface GroupHealthIndicator extends HealthIndicator {
24+
25+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/*
2+
* Copyright 2012-2019 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.actuate.health;
18+
19+
/**
20+
*
21+
* @author Stephane Nicoll
22+
*/
23+
public interface GroupReactiveHealthIndicator extends ReactiveHealthIndicator {
24+
}

spring-boot-samples/spring-boot-sample-actuator/src/main/resources/application.properties

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,12 @@ spring.jmx.enabled=true
1919
spring.jackson.serialization.write_dates_as_timestamps=false
2020

2121
management.trace.http.include=request-headers,response-headers,principal,remote-address,session-id
22+
23+
24+
management.health.groups.ready=diskSpace
25+
management.health.groups.live=example,hello,db,unknown
26+
27+
28+
29+
30+
management.endpoint.health.show-details=always

0 commit comments

Comments
 (0)