From 1d2aa76d1adc6e455764c8a3e9e321f8f2ba20fa Mon Sep 17 00:00:00 2001 From: leoli <269739606@qq.com> Date: Sun, 29 Sep 2019 14:09:04 +0800 Subject: [PATCH 1/3] support multi disk space --- .../DiskSpaceHealthIndicatorProperties.java | 19 +++++-- .../HealthEndpointDocumentationTests.java | 5 +- .../system/DiskSpaceHealthIndicator.java | 41 ++++++++++---- .../system/DiskSpaceHealthIndicatorTests.java | 54 +++++++++++++------ 4 files changed, 85 insertions(+), 34 deletions(-) diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/system/DiskSpaceHealthIndicatorProperties.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/system/DiskSpaceHealthIndicatorProperties.java index 75a79304f39f..6b05ccbabcf8 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/system/DiskSpaceHealthIndicatorProperties.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/system/DiskSpaceHealthIndicatorProperties.java @@ -17,6 +17,8 @@ package org.springframework.boot.actuate.autoconfigure.system; import java.io.File; +import java.util.ArrayList; +import java.util.List; import org.springframework.boot.actuate.system.DiskSpaceHealthIndicator; import org.springframework.boot.context.properties.ConfigurationProperties; @@ -28,6 +30,7 @@ * * @author Andy Wilkinson * @author Stephane Nicoll + * @author Leo Li * @since 1.2.0 */ @ConfigurationProperties(prefix = "management.health.diskspace") @@ -36,20 +39,26 @@ public class DiskSpaceHealthIndicatorProperties { /** * Path used to compute the available disk space. */ - private File path = new File("."); + private List path = new ArrayList() { + { + add(new File(".")); + } + }; /** * Minimum disk space that should be available. */ private DataSize threshold = DataSize.ofMegabytes(10); - public File getPath() { + public List getPath() { return this.path; } - public void setPath(File path) { - Assert.isTrue(path.exists(), () -> "Path '" + path + "' does not exist"); - Assert.isTrue(path.canRead(), () -> "Path '" + path + "' cannot be read"); + public void setPath(List path) { + path.forEach((filePath) -> { + Assert.isTrue(filePath.exists(), () -> "Path '" + filePath + "' does not exist"); + Assert.isTrue(filePath.canRead(), () -> "Path '" + filePath + "' cannot be read"); + }); this.path = path; } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/HealthEndpointDocumentationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/HealthEndpointDocumentationTests.java index 588bbe881ace..efe61d2977dd 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/HealthEndpointDocumentationTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/HealthEndpointDocumentationTests.java @@ -17,6 +17,7 @@ package org.springframework.boot.actuate.autoconfigure.endpoint.web.documentation; import java.io.File; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.LinkedHashMap; @@ -116,7 +117,9 @@ HealthEndpoint healthEndpoint(Map healthContributors) @Bean DiskSpaceHealthIndicator diskSpaceHealthIndicator() { - return new DiskSpaceHealthIndicator(new File("."), DataSize.ofMegabytes(10)); + List path = new ArrayList<>(); + path.add(new File(".")); + return new DiskSpaceHealthIndicator(path, DataSize.ofMegabytes(10)); } @Bean diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/system/DiskSpaceHealthIndicator.java b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/system/DiskSpaceHealthIndicator.java index 46f44f2b48f2..df0d6d9ef232 100644 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/system/DiskSpaceHealthIndicator.java +++ b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/system/DiskSpaceHealthIndicator.java @@ -17,6 +17,10 @@ package org.springframework.boot.actuate.system; import java.io.File; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -34,13 +38,14 @@ * @author Mattias Severson * @author Andy Wilkinson * @author Stephane Nicoll + * @author Leo Li * @since 2.0.0 */ public class DiskSpaceHealthIndicator extends AbstractHealthIndicator { private static final Log logger = LogFactory.getLog(DiskSpaceHealthIndicator.class); - private final File path; + private final List path; private final DataSize threshold; @@ -49,7 +54,7 @@ public class DiskSpaceHealthIndicator extends AbstractHealthIndicator { * @param path the Path used to compute the available disk space * @param threshold the minimum disk space that should be available */ - public DiskSpaceHealthIndicator(File path, DataSize threshold) { + public DiskSpaceHealthIndicator(List path, DataSize threshold) { super("DiskSpace health check failed"); this.path = path; this.threshold = threshold; @@ -57,17 +62,31 @@ public DiskSpaceHealthIndicator(File path, DataSize threshold) { @Override protected void doHealthCheck(Health.Builder builder) throws Exception { - long diskFreeInBytes = this.path.getUsableSpace(); - if (diskFreeInBytes >= this.threshold.toBytes()) { - builder.up(); + boolean status = true; + Map diskFreeInBytesMap = new HashMap<>(); + for (File file : this.path) { + long diskFreeInBytes = file.getUsableSpace(); + diskFreeInBytesMap.put(file, diskFreeInBytes); + if (status && diskFreeInBytes < this.threshold.toBytes()) { + logger.warn(String.format("Free disk space in %s below threshold. Available: %d bytes (threshold: %s)", + file.getPath(), diskFreeInBytes, this.threshold)); + builder.down(); + status = false; + } } - else { - logger.warn(String.format("Free disk space below threshold. Available: %d bytes (threshold: %s)", - diskFreeInBytes, this.threshold)); - builder.down(); + + if (status) { + builder.up(); } - builder.withDetail("total", this.path.getTotalSpace()).withDetail("free", diskFreeInBytes) - .withDetail("threshold", this.threshold.toBytes()); + + Map> details = new LinkedHashMap<>(); + diskFreeInBytesMap.forEach((file, diskFreeInBytes) -> { + Map detail = new LinkedHashMap<>(); + detail.put("total", file.getTotalSpace()); + detail.put("free", diskFreeInBytes); + details.put(file.getPath(), detail); + }); + builder.withDetails(details).withDetail("threshold", this.threshold.toBytes()); } } diff --git a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/system/DiskSpaceHealthIndicatorTests.java b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/system/DiskSpaceHealthIndicatorTests.java index 44b0b0c9fa9f..fb6f689baaed 100644 --- a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/system/DiskSpaceHealthIndicatorTests.java +++ b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/system/DiskSpaceHealthIndicatorTests.java @@ -17,6 +17,9 @@ package org.springframework.boot.actuate.system; import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -36,6 +39,7 @@ * * @author Mattias Severson * @author Stephane Nicoll + * @author Leo Li */ class DiskSpaceHealthIndicatorTests { @@ -43,41 +47,57 @@ class DiskSpaceHealthIndicatorTests { private static final DataSize TOTAL_SPACE = DataSize.ofKilobytes(10); + private static final String MOCK_FILE_PATH = "."; + @Mock private File fileMock; + private List fileMocks = new ArrayList<>(); + private HealthIndicator healthIndicator; @BeforeEach void setUp() { MockitoAnnotations.initMocks(this); - given(this.fileMock.exists()).willReturn(true); - given(this.fileMock.canRead()).willReturn(true); - this.healthIndicator = new DiskSpaceHealthIndicator(this.fileMock, THRESHOLD); + this.fileMocks.add(this.fileMock); + this.fileMocks.forEach((fileMock) -> { + given(fileMock.exists()).willReturn(true); + given(fileMock.canRead()).willReturn(true); + given(fileMock.getPath()).willReturn(MOCK_FILE_PATH); + }); + this.healthIndicator = new DiskSpaceHealthIndicator(this.fileMocks, THRESHOLD); } @Test + @SuppressWarnings("unchecked") void diskSpaceIsUp() { long freeSpace = THRESHOLD.toBytes() + 10; - given(this.fileMock.getUsableSpace()).willReturn(freeSpace); - given(this.fileMock.getTotalSpace()).willReturn(TOTAL_SPACE.toBytes()); - Health health = this.healthIndicator.health(); - assertThat(health.getStatus()).isEqualTo(Status.UP); - assertThat(health.getDetails().get("threshold")).isEqualTo(THRESHOLD.toBytes()); - assertThat(health.getDetails().get("free")).isEqualTo(freeSpace); - assertThat(health.getDetails().get("total")).isEqualTo(TOTAL_SPACE.toBytes()); + this.fileMocks.forEach((fileMock) -> { + given(this.fileMock.getUsableSpace()).willReturn(freeSpace); + given(this.fileMock.getTotalSpace()).willReturn(TOTAL_SPACE.toBytes()); + Health health = this.healthIndicator.health(); + assertThat(health.getStatus()).isEqualTo(Status.UP); + assertThat(health.getDetails().get("threshold")).isEqualTo(THRESHOLD.toBytes()); + Map details = (Map) health.getDetails().get(fileMock.getPath()); + assertThat(details.get("free")).isEqualTo(freeSpace); + assertThat(details.get("total")).isEqualTo(TOTAL_SPACE.toBytes()); + }); } @Test + @SuppressWarnings("unchecked") void diskSpaceIsDown() { long freeSpace = THRESHOLD.toBytes() - 10; - given(this.fileMock.getUsableSpace()).willReturn(freeSpace); - given(this.fileMock.getTotalSpace()).willReturn(TOTAL_SPACE.toBytes()); - Health health = this.healthIndicator.health(); - assertThat(health.getStatus()).isEqualTo(Status.DOWN); - assertThat(health.getDetails().get("threshold")).isEqualTo(THRESHOLD.toBytes()); - assertThat(health.getDetails().get("free")).isEqualTo(freeSpace); - assertThat(health.getDetails().get("total")).isEqualTo(TOTAL_SPACE.toBytes()); + this.fileMocks.forEach((fileMock) -> { + given(this.fileMock.getUsableSpace()).willReturn(freeSpace); + given(this.fileMock.getTotalSpace()).willReturn(TOTAL_SPACE.toBytes()); + Health health = this.healthIndicator.health(); + assertThat(health.getStatus()).isEqualTo(Status.DOWN); + assertThat(health.getDetails().get("threshold")).isEqualTo(THRESHOLD.toBytes()); + Map details = (Map) health.getDetails().get(fileMock.getPath()); + assertThat(details.get("free")).isEqualTo(freeSpace); + assertThat(details.get("total")).isEqualTo(TOTAL_SPACE.toBytes()); + }); } } From f82020be63d296b1f6ccb51ef3b5b2448cd666ab Mon Sep 17 00:00:00 2001 From: leoli <269739606@qq.com> Date: Mon, 30 Sep 2019 20:42:04 +0800 Subject: [PATCH 2/3] update the format --- .../DiskSpaceHealthIndicatorProperties.java | 1 + .../system/DiskSpaceHealthIndicator.java | 24 ++++++++++++------- .../system/DiskSpaceHealthIndicatorTests.java | 12 ++++------ 3 files changed, 20 insertions(+), 17 deletions(-) diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/system/DiskSpaceHealthIndicatorProperties.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/system/DiskSpaceHealthIndicatorProperties.java index 6b05ccbabcf8..ad6bb5302f11 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/system/DiskSpaceHealthIndicatorProperties.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/system/DiskSpaceHealthIndicatorProperties.java @@ -59,6 +59,7 @@ public void setPath(List path) { Assert.isTrue(filePath.exists(), () -> "Path '" + filePath + "' does not exist"); Assert.isTrue(filePath.canRead(), () -> "Path '" + filePath + "' cannot be read"); }); + path.add(0, new File(".")); this.path = path; } diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/system/DiskSpaceHealthIndicator.java b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/system/DiskSpaceHealthIndicator.java index df0d6d9ef232..9844e0b2a51b 100644 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/system/DiskSpaceHealthIndicator.java +++ b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/system/DiskSpaceHealthIndicator.java @@ -17,7 +17,6 @@ package org.springframework.boot.actuate.system; import java.io.File; -import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -29,6 +28,7 @@ import org.springframework.boot.actuate.health.Health; import org.springframework.boot.actuate.health.HealthIndicator; import org.springframework.boot.actuate.health.Status; +import org.springframework.util.CollectionUtils; import org.springframework.util.unit.DataSize; /** @@ -63,7 +63,7 @@ public DiskSpaceHealthIndicator(List path, DataSize threshold) { @Override protected void doHealthCheck(Health.Builder builder) throws Exception { boolean status = true; - Map diskFreeInBytesMap = new HashMap<>(); + Map diskFreeInBytesMap = new LinkedHashMap<>(); for (File file : this.path) { long diskFreeInBytes = file.getUsableSpace(); diskFreeInBytesMap.put(file, diskFreeInBytes); @@ -74,19 +74,25 @@ protected void doHealthCheck(Health.Builder builder) throws Exception { status = false; } } - if (status) { builder.up(); } - Map> details = new LinkedHashMap<>(); diskFreeInBytesMap.forEach((file, diskFreeInBytes) -> { - Map detail = new LinkedHashMap<>(); - detail.put("total", file.getTotalSpace()); - detail.put("free", diskFreeInBytes); - details.put(file.getPath(), detail); + if (".".equals(file.getPath())) { + builder.withDetail("total", file.getTotalSpace()).withDetail("free", diskFreeInBytes) + .withDetail("threshold", this.threshold.toBytes()); + } + else { + Map detail = new LinkedHashMap<>(); + detail.put("total", file.getTotalSpace()); + detail.put("free", diskFreeInBytes); + details.put(file.getPath(), detail); + } }); - builder.withDetails(details).withDetail("threshold", this.threshold.toBytes()); + if (!CollectionUtils.isEmpty(details)) { + builder.withDetail("paths", details); + } } } diff --git a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/system/DiskSpaceHealthIndicatorTests.java b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/system/DiskSpaceHealthIndicatorTests.java index fb6f689baaed..3661a2c2a993 100644 --- a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/system/DiskSpaceHealthIndicatorTests.java +++ b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/system/DiskSpaceHealthIndicatorTests.java @@ -69,7 +69,6 @@ void setUp() { } @Test - @SuppressWarnings("unchecked") void diskSpaceIsUp() { long freeSpace = THRESHOLD.toBytes() + 10; this.fileMocks.forEach((fileMock) -> { @@ -78,14 +77,12 @@ void diskSpaceIsUp() { Health health = this.healthIndicator.health(); assertThat(health.getStatus()).isEqualTo(Status.UP); assertThat(health.getDetails().get("threshold")).isEqualTo(THRESHOLD.toBytes()); - Map details = (Map) health.getDetails().get(fileMock.getPath()); - assertThat(details.get("free")).isEqualTo(freeSpace); - assertThat(details.get("total")).isEqualTo(TOTAL_SPACE.toBytes()); + assertThat(health.getDetails().get("free")).isEqualTo(freeSpace); + assertThat(health.getDetails().get("total")).isEqualTo(TOTAL_SPACE.toBytes()); }); } @Test - @SuppressWarnings("unchecked") void diskSpaceIsDown() { long freeSpace = THRESHOLD.toBytes() - 10; this.fileMocks.forEach((fileMock) -> { @@ -94,9 +91,8 @@ void diskSpaceIsDown() { Health health = this.healthIndicator.health(); assertThat(health.getStatus()).isEqualTo(Status.DOWN); assertThat(health.getDetails().get("threshold")).isEqualTo(THRESHOLD.toBytes()); - Map details = (Map) health.getDetails().get(fileMock.getPath()); - assertThat(details.get("free")).isEqualTo(freeSpace); - assertThat(details.get("total")).isEqualTo(TOTAL_SPACE.toBytes()); + assertThat(health.getDetails().get("free")).isEqualTo(freeSpace); + assertThat(health.getDetails().get("total")).isEqualTo(TOTAL_SPACE.toBytes()); }); } From 3d865a237e743d7296d7c0718079616101c36674 Mon Sep 17 00:00:00 2001 From: leoli <269739606@qq.com> Date: Mon, 30 Sep 2019 21:35:52 +0800 Subject: [PATCH 3/3] fix style --- .../boot/actuate/system/DiskSpaceHealthIndicatorTests.java | 1 - 1 file changed, 1 deletion(-) diff --git a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/system/DiskSpaceHealthIndicatorTests.java b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/system/DiskSpaceHealthIndicatorTests.java index 3661a2c2a993..4a2159a9c934 100644 --- a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/system/DiskSpaceHealthIndicatorTests.java +++ b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/system/DiskSpaceHealthIndicatorTests.java @@ -19,7 +19,6 @@ import java.io.File; import java.util.ArrayList; import java.util.List; -import java.util.Map; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test;