001/*
002 * Copyright 2012-2018 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.springframework.boot.actuate.system;
018
019import java.io.File;
020
021import org.apache.commons.logging.Log;
022import org.apache.commons.logging.LogFactory;
023
024import org.springframework.boot.actuate.health.AbstractHealthIndicator;
025import org.springframework.boot.actuate.health.Health;
026import org.springframework.boot.actuate.health.HealthIndicator;
027import org.springframework.boot.actuate.health.Status;
028import org.springframework.util.unit.DataSize;
029
030/**
031 * A {@link HealthIndicator} that checks available disk space and reports a status of
032 * {@link Status#DOWN} when it drops below a configurable threshold.
033 *
034 * @author Mattias Severson
035 * @author Andy Wilkinson
036 * @author Stephane Nicoll
037 * @since 2.0.0
038 */
039public class DiskSpaceHealthIndicator extends AbstractHealthIndicator {
040
041        private static final Log logger = LogFactory.getLog(DiskSpaceHealthIndicator.class);
042
043        private final File path;
044
045        private final DataSize threshold;
046
047        /**
048         * Create a new {@code DiskSpaceHealthIndicator} instance.
049         * @param path the Path used to compute the available disk space
050         * @param threshold the minimum disk space that should be available
051         */
052        public DiskSpaceHealthIndicator(File path, DataSize threshold) {
053                super("DiskSpace health check failed");
054                this.path = path;
055                this.threshold = threshold;
056        }
057
058        /**
059         * Create a new {@code DiskSpaceHealthIndicator} instance.
060         * @param path the Path used to compute the available disk space
061         * @param threshold the minimum disk space that should be available (in bytes)
062         * @deprecated since 2.1.0 in favor of
063         * {@link #DiskSpaceHealthIndicator(File, DataSize)}
064         */
065        @Deprecated
066        public DiskSpaceHealthIndicator(File path, long threshold) {
067                this(path, DataSize.ofBytes(threshold));
068        }
069
070        @Override
071        protected void doHealthCheck(Health.Builder builder) throws Exception {
072                long diskFreeInBytes = this.path.getUsableSpace();
073                if (diskFreeInBytes >= this.threshold.toBytes()) {
074                        builder.up();
075                }
076                else {
077                        logger.warn(String.format(
078                                        "Free disk space below threshold. "
079                                                        + "Available: %d bytes (threshold: %s)",
080                                        diskFreeInBytes, this.threshold));
081                        builder.down();
082                }
083                builder.withDetail("total", this.path.getTotalSpace())
084                                .withDetail("free", diskFreeInBytes)
085                                .withDetail("threshold", this.threshold.toBytes());
086        }
087
088}