All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.graylog2.shared.system.stats.fs.OshiFsProbe Maven / Gradle / Ivy

There is a newer version: 6.1.4
Show newest version
/*
 * Copyright (C) 2020 Graylog, Inc.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the Server Side Public License, version 1,
 * as published by MongoDB, Inc.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * Server Side Public License for more details.
 *
 * You should have received a copy of the Server Side Public License
 * along with this program. If not, see
 * .
 */
package org.graylog2.shared.system.stats.fs;

import com.google.common.collect.ImmutableSet;
import org.apache.commons.lang3.StringUtils;
import org.graylog2.Configuration;
import org.graylog2.plugin.KafkaJournalConfiguration;
import org.graylog2.shared.system.stats.OshiService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import oshi.hardware.HWDiskStore;
import oshi.hardware.HWPartition;
import oshi.hardware.HardwareAbstractionLayer;
import oshi.hardware.common.AbstractHWDiskStore;
import oshi.software.common.AbstractOSFileStore;
import oshi.software.os.FileSystem;
import oshi.software.os.OSFileStore;
import oshi.software.os.OperatingSystem;
import oshi.util.tuples.Pair;

import javax.inject.Inject;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

public class OshiFsProbe implements FsProbe {
    private static final Logger LOG = LoggerFactory.getLogger(OshiFsProbe.class);

    private final OshiService service;

    private final Set locations;
    private final Map> oshiFileSystems = new HashMap<>();

    @Inject
    public OshiFsProbe(OshiService service, Configuration configuration,
                       KafkaJournalConfiguration kafkaJournalConfiguration) {
        this.service = service;

        this.locations = ImmutableSet.of(
                configuration.getBinDir(),
                configuration.getDataDir(),
                configuration.getPluginDir(),
                kafkaJournalConfiguration.getMessageJournalDir()
        );

        init();
    }

    private void init() {
        final OperatingSystem os = service.getOs();

        final FileSystem fileSystem = os.getFileSystem();

        final HardwareAbstractionLayer hardware = service.getHal();

        for (Path location : locations) {
            Path path = location.toAbsolutePath();
            oshiFileSystems.put(path,
                    fileSystem.getFileStores().stream()
                            .filter(fs -> path.startsWith(fs.getMount()))
                            // We want the mountpoint closest to our location
                            .max(Comparator.comparingInt(p -> Paths.get(p.getMount()).getNameCount()))
                            .map(fs -> {
                                // First try search for the diskstore with the logical volume or volume name
                                Optional diskStore = hardware.getDiskStores().stream()
                                        .filter(ds -> ds.getName().equals(StringUtils.defaultIfEmpty(fs.getLogicalVolume(), fs.getVolume())))
                                        .findFirst();
                                if (diskStore.isPresent()) {
                                    return new Pair<>(fs, diskStore.get());
                                }
                                // Try to search for the diskstore with the partition of our mountpoint
                                diskStore = hardware.getDiskStores().stream()
                                        .filter(ds -> ds.getPartitions().stream().anyMatch(part -> path.startsWith(part.getMountPoint())))
                                        .max(Comparator.comparingInt(ds -> ds.getPartitions().stream()
                                                .filter(part -> path.startsWith(part.getMountPoint()))
                                                .mapToInt(part -> Paths.get(part.getMountPoint()).getNameCount())
                                                .max().orElse(0)));
                                if (diskStore.isPresent()) {
                                    return new Pair<>(fs, diskStore.get());
                                }
                                return new Pair<>(fs, generateDummyDiskStore());
                            }).orElse(new Pair<>(generateDummyFileStore(), generateDummyDiskStore())));
        }
    }

    @Override
    public FsStats fsStats() {
        final Map fsmap = oshiFileSystems.entrySet().stream().peek(
                it -> {
                    it.getValue().getA().updateAttributes();
                    it.getValue().getB().updateAttributes();
                }
        ).collect(Collectors.toMap(it -> it.getKey().toString(), it -> {

                    HWDiskStore diskStore = it.getValue().getB();
                    OSFileStore fileStore = it.getValue().getA();
                    return FsStats.Filesystem.create(it.getKey().toString(), fileStore.getMount(),
                            Optional.ofNullable(fileStore.getLogicalVolume()).orElse(fileStore.getVolume()),
                            fileStore.getDescription(), fileStore.getType(), fileStore.getTotalSpace(), fileStore.getUsableSpace(),
                            fileStore.getUsableSpace(), fileStore.getTotalSpace() - fileStore.getUsableSpace(),
                            safePercentage(fileStore.getTotalSpace() - fileStore.getUsableSpace(), fileStore.getTotalSpace(), 0),
                            fileStore.getTotalInodes(), fileStore.getFreeInodes(), fileStore.getTotalInodes() - fileStore.getFreeInodes(),
                            safePercentage(fileStore.getTotalInodes() - fileStore.getFreeInodes(), fileStore.getTotalInodes(), 0),
                            diskStore.getReads(),
                            diskStore.getWrites(),
                            diskStore.getReadBytes(),
                            diskStore.getWriteBytes(),
                            diskStore.getCurrentQueueLength(),
                            diskStore.getTimeStamp());
                })
        );
        return FsStats.create(fsmap);
    }

    private short safePercentage(long nominator, long denominator, int override) {
        return (denominator == 0) ? (short) override : (short) (nominator * 100 / denominator);
    }

    private HWDiskStore generateDummyDiskStore() {
        return new AbstractHWDiskStore("missing", "missing", "missing", 0L) {
            @Override
            public long getReads() {
                return 0;
            }

            @Override
            public long getReadBytes() {
                return 0;
            }

            @Override
            public long getWrites() {
                return 0;
            }

            @Override
            public long getWriteBytes() {
                return 0;
            }

            @Override
            public long getCurrentQueueLength() {
                return 0;
            }

            @Override
            public long getTransferTime() {
                return 0;
            }

            @Override
            public List getPartitions() {
                return null;
            }

            @Override
            public long getTimeStamp() {
                return 0;
            }

            @Override
            public boolean updateAttributes() {
                return false;
            }
        };
    }

    private OSFileStore generateDummyFileStore() {
        return new AbstractOSFileStore() {
            @Override
            public String getLogicalVolume() {
                return "missing";
            }

            @Override
            public String getDescription() {
                return "missing";
            }

            @Override
            public String getType() {
                return "dummy";
            }

            @Override
            public long getFreeSpace() {
                return 0;
            }

            @Override
            public long getUsableSpace() {
                return 0;
            }

            @Override
            public long getTotalSpace() {
                return 1;
            }

            @Override
            public long getFreeInodes() {
                return 0;
            }

            @Override
            public long getTotalInodes() {
                return 1;
            }

            @Override
            public boolean updateAttributes() {
                return false;
            }
        };
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy