org.graylog2.shared.system.stats.fs.OshiFsProbe Maven / Gradle / Ivy
/*
* 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