Work on AIX disk stats.
This commit is contained in:
parent
888cdf8dad
commit
66cd7c735b
|
@ -11,12 +11,10 @@ import org.slf4j.LoggerFactory;
|
||||||
import org.sysmon.shared.MetricExtension;
|
import org.sysmon.shared.MetricExtension;
|
||||||
import org.sysmon.shared.MetricResult;
|
import org.sysmon.shared.MetricResult;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Properties;
|
|
||||||
|
|
||||||
public class ClientRouteBuilder extends RouteBuilder {
|
public class ClientRouteBuilder extends RouteBuilder {
|
||||||
|
|
||||||
|
@ -48,7 +46,8 @@ public class ClientRouteBuilder extends RouteBuilder {
|
||||||
providers.add(provides);
|
providers.add(provides);
|
||||||
|
|
||||||
// Setup Camel route for this extension
|
// 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")
|
.bean(ext, "getMetrics")
|
||||||
//.doTry()
|
//.doTry()
|
||||||
.process(new MetricEnrichProcessor(registry))
|
.process(new MetricEnrichProcessor(registry))
|
||||||
|
|
|
@ -1,17 +1,35 @@
|
||||||
package org.sysmon.plugins.sysmon_aix;
|
package org.sysmon.plugins.sysmon_aix;
|
||||||
|
|
||||||
import org.pf4j.Extension;
|
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.MetricExtension;
|
||||||
import org.sysmon.shared.MetricResult;
|
import org.sysmon.shared.MetricResult;
|
||||||
|
import org.sysmon.shared.PluginHelper;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
@Extension
|
@Extension
|
||||||
public class AixDiskExtension implements MetricExtension {
|
public class AixDiskExtension implements MetricExtension {
|
||||||
|
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(AixProcessorExtension.class);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isSupported() {
|
public boolean isSupported() {
|
||||||
// TODO: Implement
|
|
||||||
//return System.getProperty("os.name").toLowerCase().contains("aix");
|
if(!System.getProperty("os.name").toLowerCase().contains("aix")) {
|
||||||
return false;
|
log.warn("Requires AIX.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!PluginHelper.canExecute("iostat")) {
|
||||||
|
log.warn("Requires the 'iostat' command.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -26,12 +44,25 @@ public class AixDiskExtension implements MetricExtension {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getDescription() {
|
public String getDescription() {
|
||||||
return "AIX Disk Metrics (TODO)";
|
return "AIX Disk Metrics";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MetricResult getMetrics() {
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -38,11 +38,9 @@ public class AixProcessorStat {
|
||||||
|
|
||||||
AixProcessorStat(List<String> lines) {
|
AixProcessorStat(List<String> lines) {
|
||||||
|
|
||||||
Pattern p;
|
|
||||||
for (String line : lines) {
|
for (String line : lines) {
|
||||||
|
|
||||||
if (line.startsWith("System configuration:")) {
|
if (line.startsWith("System configuration:")) {
|
||||||
p = patternAix;
|
|
||||||
Matcher matcher = patternAix.matcher(line);
|
Matcher matcher = patternAix.matcher(line);
|
||||||
if (matcher.find() && matcher.groupCount() == 7) {
|
if (matcher.find() && matcher.groupCount() == 7) {
|
||||||
type = matcher.group(1);
|
type = matcher.group(1);
|
||||||
|
|
24
plugins/sysmon-aix/src/test/groovy/AixDiskTest.groovy
Normal file
24
plugins/sysmon-aix/src/test/groovy/AixDiskTest.groovy
Normal 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
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -53,7 +53,7 @@ public class LinuxDiskExtension implements MetricExtension {
|
||||||
}
|
}
|
||||||
LinuxDiskProcLine proc2 = processFileOutput(readProcFile());
|
LinuxDiskProcLine proc2 = processFileOutput(readProcFile());
|
||||||
|
|
||||||
LinuxDiskStat stat = new LinuxDiskStat(proc2, proc1);
|
LinuxDiskStat stat = new LinuxDiskStat(proc1, proc2);
|
||||||
System.err.println("FOOBAR");
|
System.err.println("FOOBAR");
|
||||||
return new MetricResult("disk", new Measurement(stat.getTags(), stat.getFields()));
|
return new MetricResult("disk", new Measurement(stat.getTags(), stat.getFields()));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
package org.sysmon.plugins.sysmon_linux;
|
package org.sysmon.plugins.sysmon_linux;
|
||||||
|
|
||||||
public class LinuxDiskProcLine {
|
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
|
1 major number
|
||||||
|
@ -113,12 +117,12 @@ public class LinuxDiskProcLine {
|
||||||
return timeSpentOnIo;
|
return timeSpentOnIo;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Long getSectorsRead() {
|
public Long getBytesRead() {
|
||||||
return sectorsRead;
|
return sectorsRead * SECTOR_BYTE_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Long getSectorsWritten() {
|
public Long getBytesWritten() {
|
||||||
return sectorsWritten;
|
return sectorsWritten * SECTOR_BYTE_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Long getTimeSpentReading() {
|
public Long getTimeSpentReading() {
|
||||||
|
|
|
@ -21,8 +21,8 @@ public class LinuxDiskStat {
|
||||||
|
|
||||||
device = proc1.getDevice();
|
device = proc1.getDevice();
|
||||||
iotime = proc2.getTimeSpentOnIo() - proc1.getTimeSpentOnIo();
|
iotime = proc2.getTimeSpentOnIo() - proc1.getTimeSpentOnIo();
|
||||||
writes = proc2.getSectorsWritten() - proc1.getSectorsWritten();
|
writes = proc2.getBytesWritten() - proc1.getBytesWritten();
|
||||||
reads = proc2.getSectorsRead() - proc1.getSectorsRead();
|
reads = proc2.getBytesRead() - proc1.getBytesRead();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -60,7 +60,7 @@ public class LinuxProcessorExtension implements MetricExtension {
|
||||||
|
|
||||||
LinuxProcessorProcLine proc2 = processFileOutput(readProcFile());
|
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()));
|
return new MetricResult("processor", new Measurement(stat.getTags(), stat.getFields()));
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ public class LinuxProcessorStat {
|
||||||
private final float idle;
|
private final float idle;
|
||||||
private final float busy;
|
private final float busy;
|
||||||
|
|
||||||
public LinuxProcessorStat(LinuxProcessorProcLine current, LinuxProcessorProcLine previous) {
|
public LinuxProcessorStat(LinuxProcessorProcLine previous, LinuxProcessorProcLine current) {
|
||||||
|
|
||||||
long workTime = current.getCombinedTime() - previous.getCombinedTime();
|
long workTime = current.getCombinedTime() - previous.getCombinedTime();
|
||||||
|
|
||||||
|
|
|
@ -36,8 +36,8 @@ class LinuxDiskTest extends Specification {
|
||||||
then:
|
then:
|
||||||
diskStat.getTags().get("device") == "nvme0n1"
|
diskStat.getTags().get("device") == "nvme0n1"
|
||||||
diskStat.getFields().get("iotime") == 272l
|
diskStat.getFields().get("iotime") == 272l
|
||||||
diskStat.getFields().get("writes") == 78920l
|
diskStat.getFields().get("writes") == 40407040l
|
||||||
diskStat.getFields().get("reads") == 0l
|
diskStat.getFields().get("reads") == 80896l
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 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 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
|
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 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 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
|
259 3 nvme0n1p3 89207 20204 7213629 14363 42263 46782 4305376 40338 0 79728 54701 0 0 0 0 0 0
|
||||||
|
|
Loading…
Reference in a new issue