Work on AIX disk stats.

This commit is contained in:
Mark Nellemann 2021-05-13 21:53:28 +02:00
parent 888cdf8dad
commit 66cd7c735b
12 changed files with 144 additions and 23 deletions

View File

@ -11,12 +11,10 @@ import org.slf4j.LoggerFactory;
import org.sysmon.shared.MetricExtension;
import org.sysmon.shared.MetricResult;
import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
public class ClientRouteBuilder extends RouteBuilder {
@ -48,7 +46,8 @@ public class ClientRouteBuilder extends RouteBuilder {
providers.add(provides);
// Setup Camel route for this extension
from("timer:collect?fixedRate=true&period=30s")
// a unique timer name gives the timer it's own thread, otherwise it's a shared thread for other timers with same name.
from("timer:"+provides+"?fixedRate=true&period=10s")
.bean(ext, "getMetrics")
//.doTry()
.process(new MetricEnrichProcessor(registry))

View File

@ -1,17 +1,35 @@
package org.sysmon.plugins.sysmon_aix;
import org.pf4j.Extension;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sysmon.shared.Measurement;
import org.sysmon.shared.MetricExtension;
import org.sysmon.shared.MetricResult;
import org.sysmon.shared.PluginHelper;
import java.util.List;
import java.util.Map;
@Extension
public class AixDiskExtension implements MetricExtension {
private static final Logger log = LoggerFactory.getLogger(AixProcessorExtension.class);
@Override
public boolean isSupported() {
// TODO: Implement
//return System.getProperty("os.name").toLowerCase().contains("aix");
return false;
if(!System.getProperty("os.name").toLowerCase().contains("aix")) {
log.warn("Requires AIX.");
return false;
}
if(!PluginHelper.canExecute("iostat")) {
log.warn("Requires the 'iostat' command.");
return false;
}
return true;
}
@Override
@ -26,12 +44,25 @@ public class AixDiskExtension implements MetricExtension {
@Override
public String getDescription() {
return "AIX Disk Metrics (TODO)";
return "AIX Disk Metrics";
}
@Override
public MetricResult getMetrics() {
return new MetricResult("disk");
List<String> iostat = PluginHelper.executeCommand("iostat -d");
AixDiskStat diskStat = processCommandOutput(iostat);
Map<String, String> tagsMap = diskStat.getTags();
Map<String, Object> fieldsMap = diskStat.getFields();
return new MetricResult("disk", new Measurement(tagsMap, fieldsMap));
}
}
protected AixDiskStat processCommandOutput(List<String> inputLines) {
return new AixDiskStat(inputLines);
}
}

View File

@ -0,0 +1,65 @@
package org.sysmon.plugins.sysmon_aix;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class AixDiskStat {
private static final Logger log = LoggerFactory.getLogger(AixProcessorStat.class);
// Disks: % tm_act Kbps tps Kb_read Kb_wrtn
// hdisk0 1.0 752.0 81.0 740 12
private final Pattern pattern = Pattern.compile("^(hdisk\\d+)\\s+(\\d+\\.?\\d*)\\s+\\s+(\\d+\\.?\\d*)\\s+\\s+(\\d+\\.?\\d*)\\s+(\\d+)\\s+(\\d+)");
private String device;
private Float tmAct; // Indicates the percentage of time the physical disk/tape was active (bandwidth utilization for the drive).
private Float kbps; // Indicates the amount of data transferred (read or written) to the drive in KB per second.
private Float tps; // Indicates the number of transfers per second that were issued to the physical disk/tape. A transfer is an I/O request to the physical disk/tape. Multiple logical requests can be combined into a single I/O request to the disk. A transfer is of indeterminate size.
private Long kbRead; // The total number of KB read.
private Long kbWritten; // The total number of KB written.
AixDiskStat(List<String> lines) {
for (String line : lines) {
if (line.startsWith("hdisk")) {
Matcher matcher = pattern.matcher(line);
if (matcher.find() && matcher.groupCount() == 6) {
device = matcher.group(1);
tmAct = Float.parseFloat(matcher.group(2));
kbps = Float.parseFloat(matcher.group(3));
tps = Float.parseFloat(matcher.group(4));
kbRead = Long.parseLong(matcher.group(5));
kbWritten = Long.parseLong(matcher.group(6));
break;
}
}
}
}
public Map<String, String> getTags() {
Map<String, String> tags = new HashMap<>();
tags.put("device", device);
return tags;
}
public Map<String, Object> getFields() {
Map<String, Object> fields = new HashMap<>();
fields.put("reads", kbRead * 1024); // from Kb to b
fields.put("writes", kbWritten * 1024); // from Kb to b
return fields;
}
}

View File

@ -38,11 +38,9 @@ public class AixProcessorStat {
AixProcessorStat(List<String> lines) {
Pattern p;
for (String line : lines) {
if (line.startsWith("System configuration:")) {
p = patternAix;
Matcher matcher = patternAix.matcher(line);
if (matcher.find() && matcher.groupCount() == 7) {
type = matcher.group(1);

View File

@ -0,0 +1,24 @@
import org.sysmon.plugins.sysmon_aix.AixDiskExtension
import org.sysmon.plugins.sysmon_aix.AixDiskStat
import spock.lang.Specification
class AixDiskTest extends Specification {
void "test AIX iostat output processing"() {
setup:
def testFile = new File(getClass().getResource('/iostat.txt').toURI())
List<String> lines = testFile.readLines("UTF-8")
when:
AixDiskExtension extension = new AixDiskExtension()
AixDiskStat stats = extension.processCommandOutput(lines)
then:
stats.getTags().get("device") == "hdisk0"
stats.getFields().get("reads") == 757760l
stats.getFields().get("writes") == 12288l
}
}

View File

@ -53,7 +53,7 @@ public class LinuxDiskExtension implements MetricExtension {
}
LinuxDiskProcLine proc2 = processFileOutput(readProcFile());
LinuxDiskStat stat = new LinuxDiskStat(proc2, proc1);
LinuxDiskStat stat = new LinuxDiskStat(proc1, proc2);
System.err.println("FOOBAR");
return new MetricResult("disk", new Measurement(stat.getTags(), stat.getFields()));
}

View File

@ -1,6 +1,10 @@
package org.sysmon.plugins.sysmon_linux;
public class LinuxDiskProcLine {
// Sectors to bytes - each sector is 512 bytes - https://lkml.org/lkml/2015/8/17/269
static final private int SECTOR_BYTE_SIZE = 512;
/*
== ===================================
1 major number
@ -113,12 +117,12 @@ public class LinuxDiskProcLine {
return timeSpentOnIo;
}
public Long getSectorsRead() {
return sectorsRead;
public Long getBytesRead() {
return sectorsRead * SECTOR_BYTE_SIZE;
}
public Long getSectorsWritten() {
return sectorsWritten;
public Long getBytesWritten() {
return sectorsWritten * SECTOR_BYTE_SIZE;
}
public Long getTimeSpentReading() {

View File

@ -21,8 +21,8 @@ public class LinuxDiskStat {
device = proc1.getDevice();
iotime = proc2.getTimeSpentOnIo() - proc1.getTimeSpentOnIo();
writes = proc2.getSectorsWritten() - proc1.getSectorsWritten();
reads = proc2.getSectorsRead() - proc1.getSectorsRead();
writes = proc2.getBytesWritten() - proc1.getBytesWritten();
reads = proc2.getBytesRead() - proc1.getBytesRead();
}

View File

@ -60,7 +60,7 @@ public class LinuxProcessorExtension implements MetricExtension {
LinuxProcessorProcLine proc2 = processFileOutput(readProcFile());
LinuxProcessorStat stat = new LinuxProcessorStat(proc2, proc1);
LinuxProcessorStat stat = new LinuxProcessorStat(proc1, proc2);
return new MetricResult("processor", new Measurement(stat.getTags(), stat.getFields()));
}

View File

@ -11,7 +11,7 @@ public class LinuxProcessorStat {
private final float idle;
private final float busy;
public LinuxProcessorStat(LinuxProcessorProcLine current, LinuxProcessorProcLine previous) {
public LinuxProcessorStat(LinuxProcessorProcLine previous, LinuxProcessorProcLine current) {
long workTime = current.getCombinedTime() - previous.getCombinedTime();

View File

@ -36,8 +36,8 @@ class LinuxDiskTest extends Specification {
then:
diskStat.getTags().get("device") == "nvme0n1"
diskStat.getFields().get("iotime") == 272l
diskStat.getFields().get("writes") == 78920l
diskStat.getFields().get("reads") == 0l
diskStat.getFields().get("writes") == 40407040l
diskStat.getFields().get("reads") == 80896l
}
}

View File

@ -6,7 +6,7 @@
7 5 loop5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
7 6 loop6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
7 7 loop7 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
259 0 nvme0n1 89537 20714 7233785 14446 44354 46795 4305594 42289 0 79832 58659 0 0 0 0 2078 1923
259 0 nvme0n1 89537 20714 7233943 14446 44354 46795 4305594 42289 0 79832 58659 0 0 0 0 2078 1923
259 1 nvme0n1p1 126 510 7421 38 2 0 2 0 0 84 38 0 0 0 0 0 0
259 2 nvme0n1p2 100 0 7383 20 14 13 216 12 0 100 32 0 0 0 0 0 0
259 3 nvme0n1p3 89207 20204 7213629 14363 42263 46782 4305376 40338 0 79728 54701 0 0 0 0 0 0