205 lines
6.4 KiB
Java
205 lines
6.4 KiB
Java
package org.sysmon.agent.beans;
|
|
|
|
import java.io.IOException;
|
|
import java.nio.charset.StandardCharsets;
|
|
import java.nio.file.Files;
|
|
import java.nio.file.Paths;
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
|
|
import org.apache.camel.spi.Configurer;
|
|
import org.slf4j.Logger;
|
|
import org.slf4j.LoggerFactory;
|
|
import org.sysmon.shared.MetricBean;
|
|
import org.sysmon.shared.MetricMeasurement;
|
|
import org.sysmon.shared.MetricResult;
|
|
|
|
@Configurer
|
|
public class DiskBean implements MetricBean {
|
|
|
|
private final static Logger log = LoggerFactory.getLogger(DiskBean.class);
|
|
|
|
private List<LinuxDiskStat> currentDiskStats;
|
|
private List<LinuxDiskStat> previousDiskStats;
|
|
|
|
|
|
@Override
|
|
public MetricResult getMetrics() {
|
|
|
|
MetricResult result = new MetricResult("disk");
|
|
try {
|
|
copyCurrentValues();
|
|
readProcFile();
|
|
result.setMeasurementList(calculate());
|
|
} catch (IOException e) {
|
|
e.printStackTrace();
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
|
|
private void readProcFile() throws IOException {
|
|
|
|
currentDiskStats = new ArrayList<>();
|
|
List<String> allLines = Files.readAllLines(Paths.get("/proc/diskstats"), StandardCharsets.UTF_8);
|
|
for(String line : allLines) {
|
|
currentDiskStats.add(new LinuxDiskStat(line));
|
|
}
|
|
|
|
}
|
|
|
|
|
|
private void copyCurrentValues() {
|
|
|
|
if(currentDiskStats != null && currentDiskStats.size() > 0) {
|
|
previousDiskStats = new ArrayList<>(currentDiskStats);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
private List<MetricMeasurement> calculate() {
|
|
|
|
List<MetricMeasurement> measurementList = new ArrayList<>();
|
|
|
|
if(previousDiskStats == null || previousDiskStats.size() != currentDiskStats.size()) {
|
|
return measurementList;
|
|
}
|
|
|
|
|
|
for(int i = 0; i < currentDiskStats.size(); i++) {
|
|
|
|
LinuxDiskStat curStat = currentDiskStats.get(i);
|
|
LinuxDiskStat preStat = previousDiskStats.get(i);
|
|
|
|
if(curStat.device.startsWith("loop")) {
|
|
continue;
|
|
}
|
|
|
|
// TODO: Calculate differences for wanted disk io stats
|
|
measurementList.add(new MetricMeasurement(curStat.getDevice(), 0));
|
|
|
|
}
|
|
|
|
return measurementList;
|
|
}
|
|
|
|
|
|
public static class LinuxDiskStat {
|
|
/*
|
|
== ===================================
|
|
1 major number
|
|
2 minor mumber
|
|
3 device name
|
|
4 reads completed successfully
|
|
5 reads merged
|
|
6 sectors read
|
|
7 time spent reading (ms)
|
|
8 writes completed
|
|
9 writes merged
|
|
10 sectors written
|
|
11 time spent writing (ms)
|
|
12 I/Os currently in progress
|
|
13 time spent doing I/Os (ms)
|
|
14 weighted time spent doing I/Os (ms)
|
|
== ===================================
|
|
|
|
Kernel 4.18+ appends four more fields for discard
|
|
tracking putting the total at 18:
|
|
|
|
== ===================================
|
|
15 discards completed successfully
|
|
16 discards merged
|
|
17 sectors discarded
|
|
18 time spent discarding
|
|
== ===================================
|
|
|
|
Kernel 5.5+ appends two more fields for flush requests:
|
|
|
|
== =====================================
|
|
19 flush requests completed successfully
|
|
20 time spent flushing
|
|
== =====================================
|
|
*/
|
|
|
|
private final int major;
|
|
private final int minor;
|
|
private final String device; // device name
|
|
private final Long readsCompleted; // successfully
|
|
private final Long readsMerged;
|
|
private final Long sectorsRead; // 512 bytes pr. sector
|
|
private final Long timeSpentReading; // ms
|
|
private final Long writesCompleted; // successfully
|
|
private final Long writesMerged;
|
|
private final Long sectorsWritten; // 512 bytes pr. sector
|
|
private final Long timeSpentWriting; // ms
|
|
private final Long ioInProgress;
|
|
private final Long timeSpentOnIo; // ms
|
|
private final Long timeSpentOnIoWeighted;
|
|
|
|
private final Long discardsCompleted; // successfully
|
|
private final Long discardsMerged;
|
|
private final Long sectorsDiscarded; // 512 bytes pr. sector
|
|
private final Long timeSpentDiscarding; // ms
|
|
|
|
private final Long flushRequestsCompleted;
|
|
private final Long timeSpentFlushing; // ms
|
|
|
|
|
|
LinuxDiskStat(String procString) {
|
|
|
|
String[] splitStr = procString.trim().split("\\s+");
|
|
if(splitStr.length < 14) {
|
|
throw new UnsupportedOperationException("Linux proc DISK string error: " + procString);
|
|
}
|
|
|
|
this.major = Integer.parseInt(splitStr[0]);
|
|
this.minor = Integer.parseInt(splitStr[1]);
|
|
this.device = splitStr[2];
|
|
this.readsCompleted = Long.parseLong(splitStr[3]);
|
|
this.readsMerged = Long.parseLong(splitStr[4]);
|
|
this.sectorsRead = Long.parseLong(splitStr[5]);
|
|
this.timeSpentReading = Long.parseLong(splitStr[6]);
|
|
this.writesCompleted = Long.parseLong(splitStr[7]);
|
|
this.writesMerged = Long.parseLong(splitStr[8]);
|
|
this.sectorsWritten = Long.parseLong(splitStr[9]);
|
|
this.timeSpentWriting = Long.parseLong(splitStr[10]);
|
|
this.ioInProgress = Long.parseLong(splitStr[11]);
|
|
this.timeSpentOnIo = Long.parseLong(splitStr[12]);
|
|
this.timeSpentOnIoWeighted = Long.parseLong(splitStr[13]);
|
|
|
|
if(splitStr.length >= 18) {
|
|
this.discardsCompleted = Long.parseLong(splitStr[10]);
|
|
this.discardsMerged = Long.parseLong(splitStr[11]);
|
|
this.sectorsDiscarded = Long.parseLong(splitStr[12]);
|
|
this.timeSpentDiscarding = Long.parseLong(splitStr[13]);
|
|
} else {
|
|
this.discardsCompleted = null;
|
|
this.discardsMerged = null;
|
|
this.sectorsDiscarded = null;
|
|
this.timeSpentDiscarding = null;
|
|
}
|
|
|
|
if(splitStr.length == 20) {
|
|
this.flushRequestsCompleted = Long.parseLong(splitStr[14]);
|
|
this.timeSpentFlushing = Long.parseLong(splitStr[15]);
|
|
} else {
|
|
this.flushRequestsCompleted = null;
|
|
this.timeSpentFlushing = null;
|
|
}
|
|
|
|
}
|
|
|
|
public String getDevice() {
|
|
return device;
|
|
}
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|