0
# Health System
1
2
The Spring Boot Actuator health system provides comprehensive monitoring of application and infrastructure health through a flexible indicator-based architecture. It allows both built-in and custom health checks with detailed reporting and hierarchical organization.
3
4
## Capabilities
5
6
### Health Indicator Interface
7
8
Primary interface for creating health checks that report application component status.
9
10
```java { .api }
11
/**
12
* Strategy interface for health indicators
13
*/
14
@FunctionalInterface
15
public interface HealthIndicator {
16
/**
17
* Return the current health information
18
* @return the health information
19
*/
20
Health health();
21
22
/**
23
* Return the current health information
24
* @param includeDetails whether to include details in the result
25
* @return the health information
26
*/
27
default Health getHealth(boolean includeDetails) {
28
Health health = health();
29
return includeDetails ? health : health.withoutDetails();
30
}
31
}
32
```
33
34
### Reactive Health Indicator
35
36
Reactive version for asynchronous health checks using Project Reactor.
37
38
```java { .api }
39
/**
40
* Strategy interface for reactive health indicators
41
*/
42
@FunctionalInterface
43
public interface ReactiveHealthIndicator {
44
/**
45
* Return the current health information
46
* @return a Mono that emits health information
47
*/
48
Mono<Health> health();
49
50
/**
51
* Return the current health information
52
* @param includeDetails whether to include details in the result
53
* @return a Mono that emits health information
54
*/
55
default Mono<Health> getHealth(boolean includeDetails) {
56
return health().map(h -> includeDetails ? h : h.withoutDetails());
57
}
58
}
59
```
60
61
### Health Value Object
62
63
Immutable representation of health status with builder pattern support.
64
65
```java { .api }
66
/**
67
* Immutable representation of application health
68
*/
69
public final class Health {
70
71
/**
72
* Create a new Builder instance for UP status
73
* @return new Builder instance
74
*/
75
public static Builder up() {
76
return status(Status.UP);
77
}
78
79
/**
80
* Create a new Builder instance for DOWN status
81
* @return new Builder instance
82
*/
83
public static Builder down() {
84
return status(Status.DOWN);
85
}
86
87
/**
88
* Create a new Builder instance for OUT_OF_SERVICE status
89
* @return new Builder instance
90
*/
91
public static Builder outOfService() {
92
return status(Status.OUT_OF_SERVICE);
93
}
94
95
/**
96
* Create a new Builder instance for UNKNOWN status
97
* @return new Builder instance
98
*/
99
public static Builder unknown() {
100
return status(Status.UNKNOWN);
101
}
102
103
/**
104
* Create a new Builder instance for the given status
105
* @param status the health status
106
* @return new Builder instance
107
*/
108
public static Builder status(Status status) {
109
return new Builder(status);
110
}
111
112
/**
113
* Get the health status
114
* @return the health status
115
*/
116
public Status getStatus() { /* ... */ }
117
118
/**
119
* Get the health details
120
* @return the health details
121
*/
122
public Map<String, Object> getDetails() { /* ... */ }
123
124
/**
125
* Return a copy of this health without details
126
* @return health without details
127
*/
128
public Health withoutDetails() { /* ... */ }
129
130
/**
131
* Builder for Health instances
132
*/
133
public static class Builder {
134
/**
135
* Add a detail to the health
136
* @param key the detail key
137
* @param value the detail value
138
* @return this builder
139
*/
140
public Builder withDetail(String key, Object value) { /* ... */ }
141
142
/**
143
* Add details to the health
144
* @param details the details to add
145
* @return this builder
146
*/
147
public Builder withDetails(Map<String, ?> details) { /* ... */ }
148
149
/**
150
* Add an exception to the health details
151
* @param ex the exception
152
* @return this builder
153
*/
154
public Builder withException(Exception ex) { /* ... */ }
155
156
/**
157
* Build the Health instance
158
* @return the built Health
159
*/
160
public Health build() { /* ... */ }
161
}
162
}
163
```
164
165
### Health Status
166
167
Standard health status values with support for custom statuses.
168
169
```java { .api }
170
/**
171
* Value object for health status
172
*/
173
public final class Status {
174
175
/**
176
* Indicates that the component or subsystem is in an unknown state
177
*/
178
public static final Status UNKNOWN = new Status("UNKNOWN");
179
180
/**
181
* Indicates that the component or subsystem is functioning as expected
182
*/
183
public static final Status UP = new Status("UP");
184
185
/**
186
* Indicates that the component or subsystem has suffered an unexpected failure
187
*/
188
public static final Status DOWN = new Status("DOWN");
189
190
/**
191
* Indicates that the component or subsystem is out of service temporarily
192
*/
193
public static final Status OUT_OF_SERVICE = new Status("OUT_OF_SERVICE");
194
195
/**
196
* Create a new status with the given code
197
* @param code the status code
198
*/
199
public Status(String code) { /* ... */ }
200
201
/**
202
* Return the status code
203
* @return the status code
204
*/
205
public String getCode() { /* ... */ }
206
}
207
```
208
209
### Abstract Health Indicator
210
211
Base class that provides common exception handling for health indicators.
212
213
```java { .api }
214
/**
215
* Base HealthIndicator that encapsulates creation of Health instances
216
* and common exception handling
217
*/
218
public abstract class AbstractHealthIndicator implements HealthIndicator {
219
220
/**
221
* Create a new AbstractHealthIndicator
222
*/
223
protected AbstractHealthIndicator() { /* ... */ }
224
225
/**
226
* Create a new AbstractHealthIndicator with a custom description
227
* @param description the description for health check failures
228
*/
229
protected AbstractHealthIndicator(String description) { /* ... */ }
230
231
@Override
232
public final Health health() { /* ... */ }
233
234
/**
235
* Actual health check logic. If an exception is thrown the
236
* health status will be DOWN
237
* @param builder the Health builder to populate
238
* @throws Exception if health check fails
239
*/
240
protected abstract void doHealthCheck(Health.Builder builder) throws Exception;
241
}
242
```
243
244
### Health Contributor
245
246
Marker interface for health contributors that can be registered dynamically.
247
248
```java { .api }
249
/**
250
* Marker interface for health contributors
251
*/
252
public interface HealthContributor {
253
// Marker interface - no methods
254
}
255
```
256
257
### Composite Health Contributor
258
259
Groups multiple health contributors together for hierarchical health reporting.
260
261
```java { .api }
262
/**
263
* A HealthContributor that is composed of other HealthContributors
264
*/
265
public interface CompositeHealthContributor extends HealthContributor,
266
NamedContributors<HealthContributor> {
267
268
/**
269
* Create a composite health contributor from a map of contributors
270
* @param contributors the contributors
271
* @return the composite health contributor
272
*/
273
static CompositeHealthContributor fromMap(Map<String, HealthContributor> contributors) {
274
return new DefaultCompositeHealthContributor(contributors);
275
}
276
}
277
```
278
279
### Health Contributor Registry
280
281
Registry for dynamically managing health contributors at runtime.
282
283
```java { .api }
284
/**
285
* A registry for health contributors
286
*/
287
public interface HealthContributorRegistry extends HealthContributor {
288
289
/**
290
* Register a health contributor
291
* @param name the name of the contributor
292
* @param contributor the contributor
293
*/
294
void registerContributor(String name, HealthContributor contributor);
295
296
/**
297
* Unregister a health contributor
298
* @param name the name of the contributor
299
* @return the unregistered contributor or null
300
*/
301
HealthContributor unregisterContributor(String name);
302
303
/**
304
* Get a health contributor by name
305
* @param name the name of the contributor
306
* @return the contributor or null if not found
307
*/
308
HealthContributor getContributor(String name);
309
}
310
```
311
312
### Built-in Health Indicators
313
314
#### Ping Health Indicator
315
316
Simple health indicator that always returns UP status.
317
318
```java { .api }
319
/**
320
* A HealthIndicator that always returns UP
321
*/
322
public class PingHealthIndicator implements HealthIndicator {
323
324
@Override
325
public Health health() {
326
return Health.up().build();
327
}
328
}
329
```
330
331
#### Availability State Health Indicators
332
333
Health indicators that report application availability states.
334
335
```java { .api }
336
/**
337
* A HealthIndicator that reports liveness availability state
338
*/
339
public class LivenessStateHealthIndicator implements HealthIndicator {
340
341
public LivenessStateHealthIndicator(ApplicationAvailability applicationAvailability) { /* ... */ }
342
343
@Override
344
public Health health() { /* ... */ }
345
}
346
347
/**
348
* A HealthIndicator that reports readiness availability state
349
*/
350
public class ReadinessStateHealthIndicator implements HealthIndicator {
351
352
public ReadinessStateHealthIndicator(ApplicationAvailability applicationAvailability) { /* ... */ }
353
354
@Override
355
public Health health() { /* ... */ }
356
}
357
358
/**
359
* Base class for availability state health indicators
360
*/
361
public abstract class AvailabilityStateHealthIndicator implements HealthIndicator {
362
363
protected AvailabilityStateHealthIndicator(ApplicationAvailability applicationAvailability,
364
AvailabilityState failureState,
365
String statusMappingProperty) { /* ... */ }
366
}
367
```
368
369
## Usage Examples
370
371
### Creating a Custom Health Indicator
372
373
```java
374
@Component
375
public class DatabaseHealthIndicator extends AbstractHealthIndicator {
376
377
private final DatabaseService databaseService;
378
379
public DatabaseHealthIndicator(DatabaseService databaseService) {
380
this.databaseService = databaseService;
381
}
382
383
@Override
384
protected void doHealthCheck(Health.Builder builder) throws Exception {
385
if (databaseService.isConnected()) {
386
builder.up()
387
.withDetail("database", "operational")
388
.withDetail("connections", databaseService.getActiveConnections());
389
} else {
390
builder.down()
391
.withDetail("database", "connection failed")
392
.withDetail("error", "Unable to connect to database");
393
}
394
}
395
}
396
```
397
398
### Reactive Health Indicator
399
400
```java
401
@Component
402
public class ExternalServiceHealthIndicator implements ReactiveHealthIndicator {
403
404
private final WebClient webClient;
405
406
public ExternalServiceHealthIndicator(WebClient webClient) {
407
this.webClient = webClient;
408
}
409
410
@Override
411
public Mono<Health> health() {
412
return webClient.get()
413
.uri("/health")
414
.retrieve()
415
.toBodilessEntity()
416
.map(response -> Health.up()
417
.withDetail("service", "available")
418
.withDetail("status", response.getStatusCode().value())
419
.build())
420
.onErrorReturn(Health.down()
421
.withDetail("service", "unavailable")
422
.build());
423
}
424
}
425
```
426
427
### Dynamic Health Contributor Registration
428
429
```java
430
@Component
431
public class DynamicHealthManager {
432
433
private final HealthContributorRegistry healthRegistry;
434
435
public DynamicHealthManager(HealthContributorRegistry healthRegistry) {
436
this.healthRegistry = healthRegistry;
437
}
438
439
public void addServiceHealthCheck(String serviceName, HealthIndicator indicator) {
440
healthRegistry.registerContributor(serviceName, indicator);
441
}
442
443
public void removeServiceHealthCheck(String serviceName) {
444
healthRegistry.unregisterContributor(serviceName);
445
}
446
}
447
```
448
449
### Custom Health Status
450
451
```java
452
public class CustomHealthIndicator implements HealthIndicator {
453
454
public static final Status DEGRADED = new Status("DEGRADED");
455
456
@Override
457
public Health health() {
458
// Custom business logic to determine health
459
if (isFullyOperational()) {
460
return Health.up().build();
461
} else if (isPartiallyOperational()) {
462
return Health.status(DEGRADED)
463
.withDetail("mode", "degraded")
464
.withDetail("availableFeatures", getAvailableFeatures())
465
.build();
466
} else {
467
return Health.down()
468
.withDetail("reason", "all services unavailable")
469
.build();
470
}
471
}
472
}
473
```
474
475
## Configuration
476
477
Health system behavior can be configured through application properties:
478
479
```properties
480
# Show health details
481
management.endpoint.health.show-details=always
482
management.endpoint.health.show-components=always
483
484
# Configure health groups
485
management.endpoint.health.group.custom.include=db,redis,external
486
management.endpoint.health.group.custom.show-details=when-authorized
487
488
# Configure health indicator order
489
management.health.status.order=DOWN,OUT_OF_SERVICE,UNKNOWN,UP,DEGRADED
490
491
# Disable specific health indicators
492
management.health.ping.enabled=false
493
494
# Configure slow indicator threshold
495
management.endpoint.health.logging.slow-indicator-threshold=10s
496
```