Skip to content

Commit bb5b359

Browse files
committed
support multi disk space
1 parent e410931 commit bb5b359

File tree

4 files changed

+85
-34
lines changed

4 files changed

+85
-34
lines changed

spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/system/DiskSpaceHealthIndicatorProperties.java

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
package org.springframework.boot.actuate.autoconfigure.system;
1818

1919
import java.io.File;
20+
import java.util.ArrayList;
21+
import java.util.List;
2022

2123
import org.springframework.boot.actuate.system.DiskSpaceHealthIndicator;
2224
import org.springframework.boot.context.properties.ConfigurationProperties;
@@ -28,6 +30,7 @@
2830
*
2931
* @author Andy Wilkinson
3032
* @author Stephane Nicoll
33+
* @author Leo Li
3134
* @since 1.2.0
3235
*/
3336
@ConfigurationProperties(prefix = "management.health.diskspace")
@@ -36,20 +39,26 @@ public class DiskSpaceHealthIndicatorProperties {
3639
/**
3740
* Path used to compute the available disk space.
3841
*/
39-
private File path = new File(".");
42+
private List<File> path = new ArrayList<File>() {
43+
{
44+
add(new File("."));
45+
}
46+
};
4047

4148
/**
4249
* Minimum disk space that should be available.
4350
*/
4451
private DataSize threshold = DataSize.ofMegabytes(10);
4552

46-
public File getPath() {
53+
public List<File> getPath() {
4754
return this.path;
4855
}
4956

50-
public void setPath(File path) {
51-
Assert.isTrue(path.exists(), () -> "Path '" + path + "' does not exist");
52-
Assert.isTrue(path.canRead(), () -> "Path '" + path + "' cannot be read");
57+
public void setPath(List<File> path) {
58+
path.forEach((filePath) -> {
59+
Assert.isTrue(filePath.exists(), () -> "Path '" + filePath + "' does not exist");
60+
Assert.isTrue(filePath.canRead(), () -> "Path '" + filePath + "' cannot be read");
61+
});
5362
this.path = path;
5463
}
5564

spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/HealthEndpointDocumentationTests.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package org.springframework.boot.actuate.autoconfigure.endpoint.web.documentation;
1818

1919
import java.io.File;
20+
import java.util.ArrayList;
2021
import java.util.Arrays;
2122
import java.util.Collections;
2223
import java.util.LinkedHashMap;
@@ -116,7 +117,9 @@ HealthEndpoint healthEndpoint(Map<String, HealthContributor> healthContributors)
116117

117118
@Bean
118119
DiskSpaceHealthIndicator diskSpaceHealthIndicator() {
119-
return new DiskSpaceHealthIndicator(new File("."), DataSize.ofMegabytes(10));
120+
List<File> path = new ArrayList<>();
121+
path.add(new File("."));
122+
return new DiskSpaceHealthIndicator(path, DataSize.ofMegabytes(10));
120123
}
121124

122125
@Bean

spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/system/DiskSpaceHealthIndicator.java

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@
1717
package org.springframework.boot.actuate.system;
1818

1919
import java.io.File;
20+
import java.util.HashMap;
21+
import java.util.LinkedHashMap;
22+
import java.util.List;
23+
import java.util.Map;
2024

2125
import org.apache.commons.logging.Log;
2226
import org.apache.commons.logging.LogFactory;
@@ -34,13 +38,14 @@
3438
* @author Mattias Severson
3539
* @author Andy Wilkinson
3640
* @author Stephane Nicoll
41+
* @author Leo Li
3742
* @since 2.0.0
3843
*/
3944
public class DiskSpaceHealthIndicator extends AbstractHealthIndicator {
4045

4146
private static final Log logger = LogFactory.getLog(DiskSpaceHealthIndicator.class);
4247

43-
private final File path;
48+
private final List<File> path;
4449

4550
private final DataSize threshold;
4651

@@ -49,25 +54,39 @@ public class DiskSpaceHealthIndicator extends AbstractHealthIndicator {
4954
* @param path the Path used to compute the available disk space
5055
* @param threshold the minimum disk space that should be available
5156
*/
52-
public DiskSpaceHealthIndicator(File path, DataSize threshold) {
57+
public DiskSpaceHealthIndicator(List<File> path, DataSize threshold) {
5358
super("DiskSpace health check failed");
5459
this.path = path;
5560
this.threshold = threshold;
5661
}
5762

5863
@Override
5964
protected void doHealthCheck(Health.Builder builder) throws Exception {
60-
long diskFreeInBytes = this.path.getUsableSpace();
61-
if (diskFreeInBytes >= this.threshold.toBytes()) {
62-
builder.up();
65+
boolean status = true;
66+
Map<File, Long> diskFreeInBytesMap = new HashMap<>();
67+
for (File file : this.path) {
68+
long diskFreeInBytes = file.getUsableSpace();
69+
diskFreeInBytesMap.put(file, diskFreeInBytes);
70+
if (status && diskFreeInBytes < this.threshold.toBytes()) {
71+
logger.warn(String.format("Free disk space in %s below threshold. Available: %d bytes (threshold: %s)",
72+
file.getPath(), diskFreeInBytes, this.threshold));
73+
builder.down();
74+
status = false;
75+
}
6376
}
64-
else {
65-
logger.warn(String.format("Free disk space below threshold. Available: %d bytes (threshold: %s)",
66-
diskFreeInBytes, this.threshold));
67-
builder.down();
77+
78+
if (status) {
79+
builder.up();
6880
}
69-
builder.withDetail("total", this.path.getTotalSpace()).withDetail("free", diskFreeInBytes)
70-
.withDetail("threshold", this.threshold.toBytes());
81+
82+
Map<String, Map<String, Long>> details = new LinkedHashMap<>();
83+
diskFreeInBytesMap.forEach((file, diskFreeInBytes) -> {
84+
Map<String, Long> detail = new LinkedHashMap<>();
85+
detail.put("total", file.getTotalSpace());
86+
detail.put("free", diskFreeInBytes);
87+
details.put(file.getPath(), detail);
88+
});
89+
builder.withDetails(details).withDetail("threshold", this.threshold.toBytes());
7190
}
7291

7392
}

spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/system/DiskSpaceHealthIndicatorTests.java

Lines changed: 37 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@
1717
package org.springframework.boot.actuate.system;
1818

1919
import java.io.File;
20+
import java.util.ArrayList;
21+
import java.util.List;
22+
import java.util.Map;
2023

2124
import org.junit.jupiter.api.BeforeEach;
2225
import org.junit.jupiter.api.Test;
@@ -36,48 +39,65 @@
3639
*
3740
* @author Mattias Severson
3841
* @author Stephane Nicoll
42+
* @author Leo Li
3943
*/
4044
class DiskSpaceHealthIndicatorTests {
4145

4246
private static final DataSize THRESHOLD = DataSize.ofKilobytes(1);
4347

4448
private static final DataSize TOTAL_SPACE = DataSize.ofKilobytes(10);
4549

50+
private static final String MOCK_FILE_PATH = ".";
51+
4652
@Mock
4753
private File fileMock;
4854

55+
private List<File> fileMocks = new ArrayList<>();
56+
4957
private HealthIndicator healthIndicator;
5058

5159
@BeforeEach
5260
void setUp() {
5361
MockitoAnnotations.initMocks(this);
54-
given(this.fileMock.exists()).willReturn(true);
55-
given(this.fileMock.canRead()).willReturn(true);
56-
this.healthIndicator = new DiskSpaceHealthIndicator(this.fileMock, THRESHOLD);
62+
this.fileMocks.add(this.fileMock);
63+
this.fileMocks.forEach((fileMock) -> {
64+
given(fileMock.exists()).willReturn(true);
65+
given(fileMock.canRead()).willReturn(true);
66+
given(fileMock.getPath()).willReturn(MOCK_FILE_PATH);
67+
});
68+
this.healthIndicator = new DiskSpaceHealthIndicator(this.fileMocks, THRESHOLD);
5769
}
5870

5971
@Test
72+
@SuppressWarnings("unchecked")
6073
void diskSpaceIsUp() {
6174
long freeSpace = THRESHOLD.toBytes() + 10;
62-
given(this.fileMock.getUsableSpace()).willReturn(freeSpace);
63-
given(this.fileMock.getTotalSpace()).willReturn(TOTAL_SPACE.toBytes());
64-
Health health = this.healthIndicator.health();
65-
assertThat(health.getStatus()).isEqualTo(Status.UP);
66-
assertThat(health.getDetails().get("threshold")).isEqualTo(THRESHOLD.toBytes());
67-
assertThat(health.getDetails().get("free")).isEqualTo(freeSpace);
68-
assertThat(health.getDetails().get("total")).isEqualTo(TOTAL_SPACE.toBytes());
75+
this.fileMocks.forEach((fileMock) -> {
76+
given(this.fileMock.getUsableSpace()).willReturn(freeSpace);
77+
given(this.fileMock.getTotalSpace()).willReturn(TOTAL_SPACE.toBytes());
78+
Health health = this.healthIndicator.health();
79+
assertThat(health.getStatus()).isEqualTo(Status.UP);
80+
assertThat(health.getDetails().get("threshold")).isEqualTo(THRESHOLD.toBytes());
81+
Map<String, Long> details = (Map) health.getDetails().get(fileMock.getPath());
82+
assertThat(details.get("free")).isEqualTo(freeSpace);
83+
assertThat(details.get("total")).isEqualTo(TOTAL_SPACE.toBytes());
84+
});
6985
}
7086

7187
@Test
88+
@SuppressWarnings("unchecked")
7289
void diskSpaceIsDown() {
7390
long freeSpace = THRESHOLD.toBytes() - 10;
74-
given(this.fileMock.getUsableSpace()).willReturn(freeSpace);
75-
given(this.fileMock.getTotalSpace()).willReturn(TOTAL_SPACE.toBytes());
76-
Health health = this.healthIndicator.health();
77-
assertThat(health.getStatus()).isEqualTo(Status.DOWN);
78-
assertThat(health.getDetails().get("threshold")).isEqualTo(THRESHOLD.toBytes());
79-
assertThat(health.getDetails().get("free")).isEqualTo(freeSpace);
80-
assertThat(health.getDetails().get("total")).isEqualTo(TOTAL_SPACE.toBytes());
91+
this.fileMocks.forEach((fileMock) -> {
92+
given(this.fileMock.getUsableSpace()).willReturn(freeSpace);
93+
given(this.fileMock.getTotalSpace()).willReturn(TOTAL_SPACE.toBytes());
94+
Health health = this.healthIndicator.health();
95+
assertThat(health.getStatus()).isEqualTo(Status.DOWN);
96+
assertThat(health.getDetails().get("threshold")).isEqualTo(THRESHOLD.toBytes());
97+
Map<String, Long> details = (Map) health.getDetails().get(fileMock.getPath());
98+
assertThat(details.get("free")).isEqualTo(freeSpace);
99+
assertThat(details.get("total")).isEqualTo(TOTAL_SPACE.toBytes());
100+
});
81101
}
82102

83103
}

0 commit comments

Comments
 (0)