commit
84a1848eb2
15
README.md
15
README.md
|
@ -2,17 +2,20 @@
|
||||||
|
|
||||||
Java based system monitoring solution with support for plugins.
|
Java based system monitoring solution with support for plugins.
|
||||||
|
|
||||||
|
- Example Grafana [dashboard](https://bitbucket.org/mnellemann/sysmon/downloads/sysmon-example-dashboard.png) showing metrics from a host running *sysmon*.
|
||||||
|
|
||||||
## Client
|
## Components
|
||||||
|
|
||||||
Runs on your hosts and collects metrics. Metrics are aggregated and sent to the central *server*.
|
### Client
|
||||||
|
|
||||||
|
Runs on your hosts and collects metrics, which are sent to the central *server*.
|
||||||
|
|
||||||
|
|
||||||
## Server
|
### Server
|
||||||
|
|
||||||
Receives aggregated measurements from clients and saves metrics into InfluxDB.
|
Receives aggregated metrics from clients and saves these into InfluxDB.
|
||||||
|
|
||||||
|
|
||||||
## Plugins
|
### Plugins
|
||||||
|
|
||||||
Loaded by the client and provides extensions for doing the actual metric monitoring.
|
Loaded by the client and provides extensions for doing the actual collecting of metrics.
|
|
@ -19,6 +19,7 @@ subprojects {
|
||||||
|
|
||||||
implementation "org.slf4j:slf4j-api:${slf4jVersion}"
|
implementation "org.slf4j:slf4j-api:${slf4jVersion}"
|
||||||
implementation "org.slf4j:slf4j-simple:${slf4jVersion}"
|
implementation "org.slf4j:slf4j-simple:${slf4jVersion}"
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
|
|
|
@ -19,6 +19,10 @@ dependencies {
|
||||||
implementation "info.picocli:picocli:${picocliVersion}"
|
implementation "info.picocli:picocli:${picocliVersion}"
|
||||||
implementation 'org.tomlj:tomlj:1.0.0'
|
implementation 'org.tomlj:tomlj:1.0.0'
|
||||||
|
|
||||||
|
implementation(group: 'com.github.oshi', name: 'oshi-core', version: "5.7.3") {
|
||||||
|
exclude(group: "org.slf4j")
|
||||||
|
}
|
||||||
|
|
||||||
implementation group: 'org.apache.camel', name: 'camel-core', version: camelVersion
|
implementation group: 'org.apache.camel', name: 'camel-core', version: camelVersion
|
||||||
implementation group: 'org.apache.camel', name: 'camel-main', version: camelVersion
|
implementation group: 'org.apache.camel', name: 'camel-main', version: camelVersion
|
||||||
implementation group: 'org.apache.camel', name: 'camel-http', version: camelVersion
|
implementation group: 'org.apache.camel', name: 'camel-http', version: camelVersion
|
||||||
|
|
|
@ -21,7 +21,7 @@ public class ClientRouteBuilder extends RouteBuilder {
|
||||||
private static final Logger log = LoggerFactory.getLogger(ClientRouteBuilder.class);
|
private static final Logger log = LoggerFactory.getLogger(ClientRouteBuilder.class);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void configure() throws Exception {
|
public void configure() {
|
||||||
|
|
||||||
Registry registry = getContext().getRegistry();
|
Registry registry = getContext().getRegistry();
|
||||||
|
|
||||||
|
@ -45,24 +45,30 @@ public class ClientRouteBuilder extends RouteBuilder {
|
||||||
log.info(">>> Enabling extension: " + ext.getDescription());
|
log.info(">>> Enabling extension: " + ext.getDescription());
|
||||||
providers.add(provides);
|
providers.add(provides);
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: Make timer thread configurable
|
||||||
|
|
||||||
// Setup Camel route for this extension
|
// Setup Camel route for this extension
|
||||||
// a unique timer name gives the timer it's own thread, otherwise it's a shared thread for other timers with same name.
|
// 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=30s")
|
//from("timer:"+provides+"?fixedRate=true&period=30s")
|
||||||
|
from("timer:extensions?fixedRate=true&period=30s")
|
||||||
.bean(ext, "getMetrics")
|
.bean(ext, "getMetrics")
|
||||||
//.doTry()
|
//.doTry()
|
||||||
.process(new MetricEnrichProcessor(registry))
|
.process(new MetricEnrichProcessor(registry))
|
||||||
.choice().when(exchangeProperty("skip").isEqualTo(true))
|
.choice().when(exchangeProperty("skip").isEqualTo(true))
|
||||||
.log("Skipping empty: ${body}")
|
.log("Skipping empty measurement.")
|
||||||
.stop()
|
.stop()
|
||||||
.otherwise()
|
.otherwise()
|
||||||
.to("seda:metrics");
|
.to("seda:metrics?discardWhenFull=true");
|
||||||
} else {
|
} else {
|
||||||
log.info(">>> Skipping extension: " + ext.getDescription());
|
log.info(">>> Skipping extension (not supported here): " + ext.getDescription());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
from("seda:metrics")
|
// TODO: Make 'concurrentConsumers' configurable
|
||||||
|
from("seda:metrics?concurrentConsumers=1")
|
||||||
.setHeader(Exchange.HTTP_METHOD, constant("POST"))
|
.setHeader(Exchange.HTTP_METHOD, constant("POST"))
|
||||||
//.setHeader(Exchange.CONTENT_TYPE, constant("application/json"))
|
//.setHeader(Exchange.CONTENT_TYPE, constant("application/json"))
|
||||||
.doTry()
|
.doTry()
|
||||||
|
|
21
doc/AIX.md
Normal file
21
doc/AIX.md
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
# AIX Notes
|
||||||
|
|
||||||
|
Works on IBM Power VIO (Virtual IO) servers, as well as regular IBM Power AIX installations.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
We require Java 8, which should already be installed.
|
||||||
|
The RPM packages are *"noarch"* Java bytecode, so we can use the **--ignoreos** option to install:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
rpm -i --ignoreos sysmon-client.rpm sysmon-plugins.rpm
|
||||||
|
```
|
||||||
|
|
||||||
|
## Run automatically at boot
|
||||||
|
|
||||||
|
Change the *sysmon-server* URL for your environment.
|
||||||
|
|
||||||
|
```shell
|
||||||
|
mkitab 'sysmon:2:respawn:env JAVA_HOME=/usr/java8_64 /opt/sysmon/client/bin/client -s http://10.20.30.40:9925/metrics >/tmp/sysmon.log 2>&1'
|
||||||
|
init q
|
||||||
|
```
|
1736
doc/Sysmon Agent-1623356330000.json
Normal file
1736
doc/Sysmon Agent-1623356330000.json
Normal file
File diff suppressed because it is too large
Load diff
10
doc/sysmon-client.service
Normal file
10
doc/sysmon-client.service
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
[Unit]
|
||||||
|
Description=Sysmon Client Service
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
TimeoutStartSec=0
|
||||||
|
Restart=always
|
||||||
|
ExecStart=/opt/sysmon/client/bin/client -s http://10.20.30.40:9925/metrics
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=default.target
|
10
doc/sysmon-server.service
Normal file
10
doc/sysmon-server.service
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
[Unit]
|
||||||
|
Description=Sysmon Server Service
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
TimeoutStartSec=0
|
||||||
|
Restart=always
|
||||||
|
ExecStart=/opt/sysmon/server/bin/server
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=default.target
|
12
doc/systemd.md
Normal file
12
doc/systemd.md
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
# SystemD Notes
|
||||||
|
|
||||||
|
Edit the *sysmon-client.service* file and change the sysmon-server URL accordingly to your environment.
|
||||||
|
|
||||||
|
Setup as systemd service to start automatically at boot:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
cp sysmon-client.service /etc/systemd/system/
|
||||||
|
systemctl daemon-reload
|
||||||
|
systemctl enable sysmon-client
|
||||||
|
systemctl restart sysmon-client
|
||||||
|
```
|
|
@ -1,4 +1,4 @@
|
||||||
version=0.0.2
|
version=0.0.3
|
||||||
pf4jVersion=3.6.0
|
pf4jVersion=3.6.0
|
||||||
slf4jVersion=1.7.30
|
slf4jVersion=1.7.30
|
||||||
camelVersion=3.7.4
|
camelVersion=3.7.4
|
||||||
|
|
|
@ -12,6 +12,7 @@ subprojects {
|
||||||
dependencies {
|
dependencies {
|
||||||
testImplementation 'org.spockframework:spock-core:2.0-groovy-3.0'
|
testImplementation 'org.spockframework:spock-core:2.0-groovy-3.0'
|
||||||
testImplementation "org.slf4j:slf4j-api:${slf4jVersion}"
|
testImplementation "org.slf4j:slf4j-api:${slf4jVersion}"
|
||||||
|
testImplementation "org.slf4j:slf4j-simple:${slf4jVersion}"
|
||||||
testImplementation project(':shared')
|
testImplementation project(':shared')
|
||||||
|
|
||||||
implementation project(':shared')
|
implementation project(':shared')
|
||||||
|
@ -20,22 +21,13 @@ subprojects {
|
||||||
exclude(group: "org.slf4j")
|
exclude(group: "org.slf4j")
|
||||||
}
|
}
|
||||||
annotationProcessor(group: 'org.pf4j', name: 'pf4j', version: "${pf4jVersion}")
|
annotationProcessor(group: 'org.pf4j', name: 'pf4j', version: "${pf4jVersion}")
|
||||||
|
|
||||||
|
implementation(group: 'com.github.oshi', name: 'oshi-core', version: "5.7.3") {
|
||||||
|
exclude(group: "org.slf4j")
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
jar {
|
|
||||||
manifest {
|
|
||||||
attributes(
|
|
||||||
'Plugin-Id' : "${pluginId}",
|
|
||||||
'Plugin-Class' : "${pluginClass}",
|
|
||||||
'Plugin-Version' : "${pluginVersion}",
|
|
||||||
'Plugin-Provider' : "${pluginProvider}",
|
|
||||||
'Plugin-Description': "${pluginDescription}"
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}*/
|
|
||||||
|
|
||||||
task uberJar(type: Jar) {
|
task uberJar(type: Jar) {
|
||||||
from sourceSets.main.output
|
from sourceSets.main.output
|
||||||
dependsOn configurations.runtimeClasspath
|
dependsOn configurations.runtimeClasspath
|
||||||
|
@ -56,8 +48,8 @@ subprojects {
|
||||||
attributes(
|
attributes(
|
||||||
'Plugin-Id' : "${pluginId}",
|
'Plugin-Id' : "${pluginId}",
|
||||||
'Plugin-Class' : "${pluginClass}",
|
'Plugin-Class' : "${pluginClass}",
|
||||||
'Plugin-Version' : "${pluginVersion}",
|
'Plugin-Version' : "${version}",
|
||||||
'Plugin-Provider' : "${pluginProvider}",
|
'Plugin-Provider' : "System Monitor",
|
||||||
'Plugin-Description': "${pluginDescription}"
|
'Plugin-Description': "${pluginDescription}"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,3 @@
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation(group: 'com.github.oshi', name: 'oshi-core', version: "5.7.3") {
|
|
||||||
exclude(group: "org.slf4j")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,91 +0,0 @@
|
||||||
package sysmon.plugins.os_aix;
|
|
||||||
|
|
||||||
import org.pf4j.Extension;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import oshi.SystemInfo;
|
|
||||||
import oshi.hardware.HardwareAbstractionLayer;
|
|
||||||
import sysmon.shared.Measurement;
|
|
||||||
import sysmon.shared.MetricExtension;
|
|
||||||
import sysmon.shared.MetricResult;
|
|
||||||
import 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);
|
|
||||||
|
|
||||||
private final SystemInfo systemInfo;
|
|
||||||
private final HardwareAbstractionLayer hardwareAbstractionLayer;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isSupported() {
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public AixDiskExtension() {
|
|
||||||
systemInfo = new SystemInfo();
|
|
||||||
hardwareAbstractionLayer = systemInfo.getHardware();
|
|
||||||
log.warn(systemInfo.getOperatingSystem().toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getName() {
|
|
||||||
return "aix-disk";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getProvides() {
|
|
||||||
return "disk";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getDescription() {
|
|
||||||
return "AIX Disk Metrics";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MetricResult getMetrics() {
|
|
||||||
|
|
||||||
long writeBytes = hardwareAbstractionLayer.getDiskStores().get(0).getWriteBytes();
|
|
||||||
log.warn(String.format("Disk 0 - Write Bytes: %d", writeBytes));
|
|
||||||
|
|
||||||
long readBytes = hardwareAbstractionLayer.getDiskStores().get(0).getReadBytes();
|
|
||||||
log.warn(String.format("Disk 0 - Read Bytes: %d", readBytes));
|
|
||||||
|
|
||||||
long memAvailable = hardwareAbstractionLayer.getMemory().getAvailable();
|
|
||||||
log.warn(String.format("Memory - Available: %d", memAvailable));
|
|
||||||
|
|
||||||
List<String> iostat = PluginHelper.executeCommand("iostat -d 1 1");
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,53 +0,0 @@
|
||||||
package sysmon.plugins.os_aix;
|
|
||||||
|
|
||||||
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 {
|
|
||||||
|
|
||||||
// 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 = 0.0f; // Indicates the percentage of time the physical disk/tape was active (bandwidth utilization for the drive).
|
|
||||||
private float kbps = 0.0f; // Indicates the amount of data transferred (read or written) to the drive in KB per second.
|
|
||||||
private float tps = 0.0f; // 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 = 0L; // The total number of KB read.
|
|
||||||
private long kbWritten = 0L; // 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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<String, String> getTags() {
|
|
||||||
return new HashMap<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<String, Object> getFields() {
|
|
||||||
Map<String, Object> fields = new HashMap<>();
|
|
||||||
fields.put("reads", kbRead * 1024); // from Kb to bytes
|
|
||||||
fields.put("writes", kbWritten * 1024); // from Kb to bytes
|
|
||||||
fields.put("kbps", (int) kbps);
|
|
||||||
fields.put("tps", (int) tps);
|
|
||||||
return fields;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,68 +0,0 @@
|
||||||
package sysmon.plugins.os_aix;
|
|
||||||
|
|
||||||
import org.pf4j.Extension;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import sysmon.shared.Measurement;
|
|
||||||
import sysmon.shared.MetricExtension;
|
|
||||||
import sysmon.shared.MetricResult;
|
|
||||||
import sysmon.shared.PluginHelper;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
@Extension
|
|
||||||
public class AixMemoryExtension implements MetricExtension {
|
|
||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(AixMemoryExtension.class);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isSupported() {
|
|
||||||
|
|
||||||
if(!System.getProperty("os.name").toLowerCase().contains("aix")) {
|
|
||||||
log.warn("Requires AIX.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!PluginHelper.canExecute("svmon")) {
|
|
||||||
log.warn("Requires the 'svmon' command.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getName() {
|
|
||||||
return "aix-memory";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getProvides() {
|
|
||||||
return "memory";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getDescription() {
|
|
||||||
return "AIX Memory Metrics";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MetricResult getMetrics() {
|
|
||||||
|
|
||||||
//List<String> svmon = PluginHelper.executeCommand("svmon -G -O unit=KB");
|
|
||||||
List<String> svmon = PluginHelper.executeCommand("svmon -G -O summary=longreal,unit=KB");
|
|
||||||
AixMemoryStat memoryStat = processCommandOutput(svmon);
|
|
||||||
|
|
||||||
Map<String, String> tagsMap = memoryStat.getTags();
|
|
||||||
Map<String, Object> fieldsMap = memoryStat.getFields();
|
|
||||||
|
|
||||||
return new MetricResult("memory", new Measurement(tagsMap, fieldsMap));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected AixMemoryStat processCommandOutput(List<String> inputLines) {
|
|
||||||
return new AixMemoryStat(inputLines);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,60 +0,0 @@
|
||||||
package sysmon.plugins.os_aix;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.regex.Matcher;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
public class AixMemoryStat {
|
|
||||||
|
|
||||||
private final Pattern pattern = Pattern.compile("^\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)");
|
|
||||||
|
|
||||||
private long total;
|
|
||||||
private long used;
|
|
||||||
private long free;
|
|
||||||
private long pin;
|
|
||||||
private long virtual;
|
|
||||||
private long available;
|
|
||||||
private long paged;
|
|
||||||
|
|
||||||
AixMemoryStat(List<String> lines) {
|
|
||||||
for (String line : lines) {
|
|
||||||
Matcher matcher = pattern.matcher(line);
|
|
||||||
if (matcher.find() && matcher.groupCount() == 7) {
|
|
||||||
total = Long.parseLong(matcher.group(1));
|
|
||||||
used = Long.parseLong(matcher.group(2));
|
|
||||||
free = Long.parseLong(matcher.group(3));
|
|
||||||
pin = Long.parseLong(matcher.group(4));
|
|
||||||
virtual = Long.parseLong(matcher.group(5));
|
|
||||||
available = Long.parseLong(matcher.group(6));
|
|
||||||
paged = Long.parseLong(matcher.group(7));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public Map<String, String> getTags() {
|
|
||||||
return new HashMap<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public Map<String, Object> getFields() {
|
|
||||||
|
|
||||||
float usage = ((float) (total - available) / total ) * 100;
|
|
||||||
//BigDecimal usage = new BigDecimal(tmp).setScale(2, RoundingMode.HALF_UP);
|
|
||||||
|
|
||||||
Map<String, Object> fields = new HashMap<>();
|
|
||||||
fields.put("total", total);
|
|
||||||
fields.put("used", used);
|
|
||||||
fields.put("free", free);
|
|
||||||
fields.put("pin", pin);
|
|
||||||
fields.put("virtual", virtual);
|
|
||||||
fields.put("available", available);
|
|
||||||
fields.put("paged", paged);
|
|
||||||
fields.put("usage", usage);
|
|
||||||
return fields;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -0,0 +1,74 @@
|
||||||
|
package sysmon.plugins.os_aix;
|
||||||
|
|
||||||
|
import org.pf4j.Extension;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import sysmon.shared.Measurement;
|
||||||
|
import sysmon.shared.MetricExtension;
|
||||||
|
import sysmon.shared.MetricResult;
|
||||||
|
import sysmon.shared.PluginHelper;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
// Disabled
|
||||||
|
//@Extension
|
||||||
|
public class AixNetstatExtension implements MetricExtension {
|
||||||
|
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(AixNetstatExtension.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isSupported() {
|
||||||
|
|
||||||
|
if(!System.getProperty("os.name").toLowerCase().contains("aix")) {
|
||||||
|
log.warn("Requires AIX.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!PluginHelper.canExecute("netstat")) {
|
||||||
|
log.warn("Requires the 'netstat' command.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "aix-network-netstat";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getProvides() {
|
||||||
|
return "network-netstat";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDescription() {
|
||||||
|
return "AIX Netstat Metrics";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MetricResult getMetrics() throws Exception {
|
||||||
|
|
||||||
|
Map<String, String> tagsMap = null;
|
||||||
|
Map<String, Object> fieldsMap = null;
|
||||||
|
|
||||||
|
try (InputStream buf = PluginHelper.executeCommand("netstat -s -f inet")) {
|
||||||
|
AixNetstatParser parser = processCommandOutput(buf);
|
||||||
|
tagsMap = parser.getTags();
|
||||||
|
fieldsMap = parser.getFields();
|
||||||
|
}
|
||||||
|
|
||||||
|
log.debug(fieldsMap.toString());
|
||||||
|
return new MetricResult("network_netstat", new Measurement(tagsMap, fieldsMap));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected AixNetstatParser processCommandOutput(InputStream input) throws IOException {
|
||||||
|
return new AixNetstatParser(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,156 @@
|
||||||
|
package sysmon.plugins.os_aix;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class AixNetstatParser {
|
||||||
|
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(AixNetstatParser.class);
|
||||||
|
|
||||||
|
private long ipTotalPacketsReceived;
|
||||||
|
private long ipForwarded;
|
||||||
|
|
||||||
|
private long tcpConnectionsEstablished;
|
||||||
|
private long tcpPacketsReceved;
|
||||||
|
private long tcpPacketsSent;
|
||||||
|
|
||||||
|
private long udpPacketsReceived;
|
||||||
|
private long udpPacketsSent;
|
||||||
|
|
||||||
|
|
||||||
|
public AixNetstatParser(InputStream inputStream) throws IOException {
|
||||||
|
|
||||||
|
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
|
||||||
|
while (reader.ready()) {
|
||||||
|
String line = reader.readLine();
|
||||||
|
log.debug("AixNetstatParser() - Line: " + line);
|
||||||
|
|
||||||
|
if(line.startsWith("tcp:")) {
|
||||||
|
parseTcp(reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(line.startsWith("udp:")) {
|
||||||
|
parseUdp(reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(line.startsWith("ip:")) {
|
||||||
|
parseIp(reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
inputStream.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected void parseIp(BufferedReader reader) throws IOException {
|
||||||
|
|
||||||
|
while (reader.ready()) {
|
||||||
|
reader.mark(64);
|
||||||
|
String line = reader.readLine();
|
||||||
|
|
||||||
|
if(!line.startsWith(" ")) {
|
||||||
|
reader.reset();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
line = line.trim();
|
||||||
|
|
||||||
|
if(line.matches("(\\d+) total packets received")) {
|
||||||
|
ipTotalPacketsReceived = getFirstLong(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(line.matches("(\\d+) packets forwarded")) {
|
||||||
|
ipForwarded = getFirstLong(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected void parseTcp(BufferedReader reader) throws IOException {
|
||||||
|
|
||||||
|
while (reader.ready()) {
|
||||||
|
reader.mark(64);
|
||||||
|
String line = reader.readLine();
|
||||||
|
|
||||||
|
if(!line.startsWith(" ")) {
|
||||||
|
reader.reset();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
line = line.trim();
|
||||||
|
|
||||||
|
if(line.matches("(\\d+) connections established \\(including accepts\\)")) {
|
||||||
|
tcpConnectionsEstablished = getFirstLong(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(line.matches("(\\d+) packets received")) {
|
||||||
|
tcpPacketsReceved = getFirstLong(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(line.matches("(\\d+) packets sent")) {
|
||||||
|
tcpPacketsSent = getFirstLong(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void parseUdp(BufferedReader reader) throws IOException {
|
||||||
|
|
||||||
|
while (reader.ready()) {
|
||||||
|
reader.mark(64);
|
||||||
|
String line = reader.readLine();
|
||||||
|
|
||||||
|
if(!line.startsWith(" ")) {
|
||||||
|
reader.reset();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
line = line.trim();
|
||||||
|
|
||||||
|
if(line.matches("(\\d+) datagrams received")) {
|
||||||
|
udpPacketsReceived = getFirstLong(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(line.matches("(\\d+) datagrams output")) {
|
||||||
|
udpPacketsSent = getFirstLong(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Map<String, String> getTags() {
|
||||||
|
return new HashMap<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, Object> getFields() {
|
||||||
|
Map<String, Object> fields = new HashMap<>();
|
||||||
|
fields.put("ip_forwarded", ipForwarded);
|
||||||
|
fields.put("ip_received", ipTotalPacketsReceived);
|
||||||
|
|
||||||
|
fields.put("tcp_connections", tcpConnectionsEstablished);
|
||||||
|
fields.put("tcp_pkts_recv", tcpPacketsReceved);
|
||||||
|
fields.put("tcp_pkts_sent", tcpPacketsSent);
|
||||||
|
|
||||||
|
fields.put("udp_pkts_recv", udpPacketsReceived);
|
||||||
|
fields.put("udp_pkts_sent", udpPacketsSent);
|
||||||
|
|
||||||
|
return fields;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Long getFirstLong(String line) {
|
||||||
|
return Long.parseLong(line.substring(0, line.indexOf(" ")));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -8,6 +8,8 @@ import sysmon.shared.MetricExtension;
|
||||||
import sysmon.shared.MetricResult;
|
import sysmon.shared.MetricResult;
|
||||||
import sysmon.shared.PluginHelper;
|
import sysmon.shared.PluginHelper;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
@ -40,7 +42,7 @@ public class AixProcessorExtension implements MetricExtension {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getProvides() {
|
public String getProvides() {
|
||||||
return "processor";
|
return "processor-lpar";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -49,20 +51,23 @@ public class AixProcessorExtension implements MetricExtension {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MetricResult getMetrics() {
|
public MetricResult getMetrics() throws Exception {
|
||||||
|
|
||||||
List<String> lparstat = PluginHelper.executeCommand("lparstat 1 1");
|
Map<String, String> tagsMap = null;
|
||||||
AixProcessorStat processorStat = processCommandOutput(lparstat);
|
Map<String, Object> fieldsMap = null;
|
||||||
|
|
||||||
Map<String, String> tagsMap = processorStat.getTags();
|
try (InputStream buf = PluginHelper.executeCommand("lparstat 1 1")) {
|
||||||
Map<String, Object> fieldsMap = processorStat.getFields();
|
AixProcessorStat processorStat = processCommandOutput(buf);
|
||||||
|
tagsMap = processorStat.getTags();
|
||||||
|
fieldsMap = processorStat.getFields();
|
||||||
|
}
|
||||||
|
|
||||||
return new MetricResult("processor", new Measurement(tagsMap, fieldsMap));
|
return new MetricResult("processor_lpar", new Measurement(tagsMap, fieldsMap));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected AixProcessorStat processCommandOutput(List<String> inputLines) {
|
protected AixProcessorStat processCommandOutput(InputStream input) throws IOException {
|
||||||
return new AixProcessorStat(inputLines);
|
return new AixProcessorStat(input);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,12 @@
|
||||||
package sysmon.plugins.os_aix;
|
package sysmon.plugins.os_aix;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -8,8 +15,13 @@ import java.util.regex.Pattern;
|
||||||
|
|
||||||
public class AixProcessorStat {
|
public class AixProcessorStat {
|
||||||
|
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(AixProcessorStat.class);
|
||||||
|
|
||||||
// System configuration: type=Shared mode=Uncapped smt=8 lcpu=8 mem=4096MB psize=19 ent=0.50
|
// System configuration: type=Shared mode=Uncapped smt=8 lcpu=8 mem=4096MB psize=19 ent=0.50
|
||||||
private final Pattern patternAix = Pattern.compile("^System configuration: type=(\\S+) mode=(\\S+) smt=(\\d+) lcpu=(\\d+) mem=(\\d+)MB psize=(\\d+) ent=(\\d+\\.?\\d*)");
|
private final Pattern patternAixShared = Pattern.compile("^System configuration: type=(\\S+) mode=(\\S+) smt=(\\d+) lcpu=(\\d+) mem=(\\d+)MB psize=(\\d+) ent=(\\d+\\.?\\d*)");
|
||||||
|
|
||||||
|
// System configuration: type=Dedicated mode=Donating smt=8 lcpu=16 mem=4096MB
|
||||||
|
private final Pattern patternAixDedicated = Pattern.compile("^System configuration: type=(\\S+) mode=(\\S+) smt=(\\d+) lcpu=(\\d+) mem=(\\d+)MB");
|
||||||
|
|
||||||
// type=Shared mode=Uncapped smt=8 lcpu=4 mem=4101120 kB cpus=24 ent=4.00
|
// type=Shared mode=Uncapped smt=8 lcpu=4 mem=4101120 kB cpus=24 ent=4.00
|
||||||
private final Pattern patternLinux = Pattern.compile("^type=(\\S+) mode=(\\S+) smt=(\\d+) lcpu=(\\d+) mem=(\\d+) kB cpus=(\\d+) ent=(\\d+\\.?\\d*)");
|
private final Pattern patternLinux = Pattern.compile("^type=(\\S+) mode=(\\S+) smt=(\\d+) lcpu=(\\d+) mem=(\\d+) kB cpus=(\\d+) ent=(\\d+\\.?\\d*)");
|
||||||
|
@ -31,12 +43,15 @@ public class AixProcessorStat {
|
||||||
private final float lbusy; // Indicates the percentage of logical processor(s) utilization that occurred while executing at the user and system level.
|
private final float lbusy; // Indicates the percentage of logical processor(s) utilization that occurred while executing at the user and system level.
|
||||||
|
|
||||||
|
|
||||||
AixProcessorStat(List<String> lines) {
|
public AixProcessorStat(InputStream inputStream) throws IOException {
|
||||||
|
|
||||||
for (String line : lines) {
|
String lastLine = null;
|
||||||
|
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
|
||||||
|
while(reader.ready()) {
|
||||||
|
String line = reader.readLine();
|
||||||
|
|
||||||
if (line.startsWith("System configuration:")) {
|
if (line.startsWith("System configuration:")) {
|
||||||
Matcher matcher = patternAix.matcher(line);
|
Matcher matcher = patternAixShared.matcher(line);
|
||||||
if (matcher.find() && matcher.groupCount() == 7) {
|
if (matcher.find() && matcher.groupCount() == 7) {
|
||||||
type = matcher.group(1);
|
type = matcher.group(1);
|
||||||
mode = matcher.group(2);
|
mode = matcher.group(2);
|
||||||
|
@ -45,6 +60,13 @@ public class AixProcessorStat {
|
||||||
psize = Integer.parseInt(matcher.group(5));
|
psize = Integer.parseInt(matcher.group(5));
|
||||||
ent = Float.parseFloat(matcher.group(7));
|
ent = Float.parseFloat(matcher.group(7));
|
||||||
}
|
}
|
||||||
|
matcher = patternAixDedicated.matcher(line);
|
||||||
|
if (matcher.find() && matcher.groupCount() == 5) {
|
||||||
|
type = matcher.group(1);
|
||||||
|
mode = matcher.group(2);
|
||||||
|
smt = Integer.parseInt(matcher.group(3));
|
||||||
|
lcpu = Integer.parseInt(matcher.group(4));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (line.startsWith("type=")) {
|
if (line.startsWith("type=")) {
|
||||||
|
@ -60,12 +82,14 @@ public class AixProcessorStat {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lastLine = line;
|
||||||
}
|
}
|
||||||
|
|
||||||
String lparstat = lines.get(lines.size() -1);
|
//String lparstat = lines.get(lines.size() -1);
|
||||||
String[] splitStr = lparstat.trim().split("\\s+");
|
String[] splitStr = lastLine.trim().split("\\s+");
|
||||||
if(splitStr.length < 9) {
|
if(type.equalsIgnoreCase("shared") && splitStr.length < 9 ||
|
||||||
throw new UnsupportedOperationException("lparstat string error: " + lparstat);
|
type.equalsIgnoreCase("dedicated") && splitStr.length < 8) {
|
||||||
|
throw new UnsupportedOperationException("lparstat string error: " + lastLine);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.user = Float.parseFloat(splitStr[0]);
|
this.user = Float.parseFloat(splitStr[0]);
|
||||||
|
@ -73,9 +97,15 @@ public class AixProcessorStat {
|
||||||
this.wait = Float.parseFloat(splitStr[2]);
|
this.wait = Float.parseFloat(splitStr[2]);
|
||||||
this.idle = Float.parseFloat(splitStr[3]);
|
this.idle = Float.parseFloat(splitStr[3]);
|
||||||
this.physc = Float.parseFloat(splitStr[4]);
|
this.physc = Float.parseFloat(splitStr[4]);
|
||||||
|
if(type.equalsIgnoreCase("shared")) {
|
||||||
this.entc = Float.parseFloat(splitStr[5]);
|
this.entc = Float.parseFloat(splitStr[5]);
|
||||||
this.lbusy = Float.parseFloat(splitStr[6]);
|
this.lbusy = Float.parseFloat(splitStr[6]);
|
||||||
|
} else {
|
||||||
|
this.entc = 0f;
|
||||||
|
this.lbusy = 0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
inputStream.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
public float getUser() {
|
public float getUser() {
|
||||||
|
|
|
@ -1,26 +0,0 @@
|
||||||
import sysmon.plugins.os_aix.AixDiskExtension
|
|
||||||
import sysmon.plugins.os_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
|
|
||||||
stats.getFields().get("kbps") == 752L
|
|
||||||
stats.getFields().get("tps") == 81L
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,29 +0,0 @@
|
||||||
import sysmon.plugins.os_aix.AixMemoryExtension
|
|
||||||
import sysmon.plugins.os_aix.AixMemoryStat
|
|
||||||
import spock.lang.Specification
|
|
||||||
|
|
||||||
class AixMemoryTest extends Specification {
|
|
||||||
|
|
||||||
void "test AIX svmon output processing"() {
|
|
||||||
|
|
||||||
setup:
|
|
||||||
def testFile = new File(getClass().getResource('/svmon.txt').toURI())
|
|
||||||
List<String> lines = testFile.readLines("UTF-8")
|
|
||||||
|
|
||||||
when:
|
|
||||||
AixMemoryExtension extension = new AixMemoryExtension()
|
|
||||||
AixMemoryStat stats = extension.processCommandOutput(lines)
|
|
||||||
|
|
||||||
then:
|
|
||||||
stats.getFields().get("total") == 4194304L
|
|
||||||
stats.getFields().get("used") == 4065060L
|
|
||||||
stats.getFields().get("free") == 129244L
|
|
||||||
stats.getFields().get("pin") == 1878240L
|
|
||||||
stats.getFields().get("virtual") == 2784988L
|
|
||||||
stats.getFields().get("available") == 1058012L
|
|
||||||
stats.getFields().get("paged") == 524288L
|
|
||||||
stats.getFields().get("usage") == 74.775024f
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
25
plugins/os-aix/src/test/groovy/AixNetstatTest.groovy
Normal file
25
plugins/os-aix/src/test/groovy/AixNetstatTest.groovy
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
import spock.lang.Specification
|
||||||
|
import sysmon.plugins.os_aix.AixNetstatParser
|
||||||
|
|
||||||
|
class AixNetstatTest extends Specification {
|
||||||
|
|
||||||
|
void "test netstat parsing"() {
|
||||||
|
|
||||||
|
setup:
|
||||||
|
InputStream inputStream = getClass().getResourceAsStream('/netstat-aix.txt');
|
||||||
|
|
||||||
|
when:
|
||||||
|
AixNetstatParser parser = new AixNetstatParser(inputStream)
|
||||||
|
|
||||||
|
then:
|
||||||
|
parser.getFields().size() > 0
|
||||||
|
parser.getFields().get('ip_received') == 76229L
|
||||||
|
parser.getFields().get('ip_forwarded') == 24L
|
||||||
|
parser.getFields().get('tcp_connections') == 85L
|
||||||
|
parser.getFields().get('tcp_pkts_sent') == 31274L
|
||||||
|
parser.getFields().get('tcp_pkts_recv') == 39830L
|
||||||
|
parser.getFields().get('udp_pkts_sent') == 26332L
|
||||||
|
parser.getFields().get('udp_pkts_recv') == 34559L
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -4,15 +4,14 @@ import spock.lang.Specification
|
||||||
|
|
||||||
class AixProcessorTest extends Specification {
|
class AixProcessorTest extends Specification {
|
||||||
|
|
||||||
void "test AIX lparstat output processing"() {
|
void "test AIX lparstat shared output processing"() {
|
||||||
|
|
||||||
setup:
|
setup:
|
||||||
def testFile = new File(getClass().getResource('/lparstat-aix.txt').toURI())
|
InputStream inputStream = getClass().getResourceAsStream('/lparstat-aix-shared.txt');
|
||||||
List<String> lines = testFile.readLines("UTF-8")
|
|
||||||
|
|
||||||
when:
|
when:
|
||||||
AixProcessorExtension extension = new AixProcessorExtension()
|
AixProcessorExtension extension = new AixProcessorExtension()
|
||||||
AixProcessorStat stats = extension.processCommandOutput(lines)
|
AixProcessorStat stats = extension.processCommandOutput(inputStream)
|
||||||
|
|
||||||
then:
|
then:
|
||||||
stats.getUser() == 83.7f
|
stats.getUser() == 83.7f
|
||||||
|
@ -20,19 +19,37 @@ class AixProcessorTest extends Specification {
|
||||||
stats.getWait() == 0.0f
|
stats.getWait() == 0.0f
|
||||||
stats.getIdle() == 13.0f
|
stats.getIdle() == 13.0f
|
||||||
stats.getFields().get("ent") == 0.50f
|
stats.getFields().get("ent") == 0.50f
|
||||||
|
stats.getFields().get("type") == "Shared"
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void "test AIX lparstat dedicated output processing"() {
|
||||||
|
|
||||||
|
setup:
|
||||||
|
InputStream inputStream = getClass().getResourceAsStream('/lparstat-aix-dedicated.txt');
|
||||||
|
|
||||||
|
when:
|
||||||
|
AixProcessorExtension extension = new AixProcessorExtension()
|
||||||
|
AixProcessorStat stats = extension.processCommandOutput(inputStream)
|
||||||
|
|
||||||
|
then:
|
||||||
|
stats.getUser() == 0.1f
|
||||||
|
stats.getSys() == 0.2f
|
||||||
|
stats.getWait() == 0.0f
|
||||||
|
stats.getIdle() == 99.7f
|
||||||
|
stats.getFields().get("physc") == 0.07f
|
||||||
|
stats.getFields().get("type") == "Dedicated"
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void "test Linux lparstat output processing"() {
|
void "test Linux lparstat output processing"() {
|
||||||
|
|
||||||
setup:
|
setup:
|
||||||
def testFile = new File(getClass().getResource('/lparstat-linux.txt').toURI())
|
InputStream inputStream = getClass().getResourceAsStream('/lparstat-linux.txt');
|
||||||
List<String> lines = testFile.readLines("UTF-8")
|
|
||||||
|
|
||||||
when:
|
when:
|
||||||
AixProcessorExtension extension = new AixProcessorExtension()
|
AixProcessorExtension extension = new AixProcessorExtension()
|
||||||
AixProcessorStat stats = extension.processCommandOutput(lines)
|
AixProcessorStat stats = extension.processCommandOutput(inputStream)
|
||||||
|
|
||||||
then:
|
then:
|
||||||
stats.getUser() == 0.03f
|
stats.getUser() == 0.03f
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
Disks: % tm_act Kbps tps Kb_read Kb_wrtn
|
|
||||||
cd0 0.0 0.0 0.0 0 0
|
|
||||||
hdisk0 1.0 752.0 81.0 740 12
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
|
||||||
|
System configuration: type=Dedicated mode=Donating smt=8 lcpu=16 mem=4096MB
|
||||||
|
|
||||||
|
%user %sys %wait %idle physc vcsw %nsp %utcyc
|
||||||
|
----- ----- ------ ------ ----- ----- ----- ------
|
||||||
|
0.1 0.2 0.0 99.7 0.07 1014627468 132 24.21
|
|
@ -1,15 +0,0 @@
|
||||||
|
|
||||||
System configuration: lcpu=8 ent=0.5 mode=Uncapped
|
|
||||||
|
|
||||||
|
|
||||||
vcpu lcpu us sy wa id pbusy pc VTB(ms)
|
|
||||||
---- ---- ---- ---- ----- ----- ----- ----- -------
|
|
||||||
0 33.51 5.62 0.11 60.77 0.00[ 39.1%] 0.00[ 0.1%] 1784440
|
|
||||||
0 13.38 3.96 0.05 4.81 0.00[ 17.3%] 0.00[ 22.2%] -
|
|
||||||
1 8.41 0.72 0.04 7.59 0.00[ 9.1%] 0.00[ 16.8%] -
|
|
||||||
2 5.19 0.35 0.01 6.45 0.00[ 5.5%] 0.00[ 12.0%] -
|
|
||||||
3 4.42 0.28 0.01 8.42 0.00[ 4.7%] 0.00[ 13.1%] -
|
|
||||||
4 0.57 0.07 0.00 7.47 0.00[ 0.6%] 0.00[ 8.1%] -
|
|
||||||
5 0.51 0.06 0.00 9.28 0.00[ 0.6%] 0.00[ 9.8%] -
|
|
||||||
6 0.49 0.07 0.00 7.49 0.00[ 0.6%] 0.00[ 8.1%] -
|
|
||||||
7 0.54 0.10 0.00 9.26 0.00[ 0.6%] 0.00[ 9.9%] -
|
|
157
plugins/os-aix/src/test/resources/netstat-aix.txt
Normal file
157
plugins/os-aix/src/test/resources/netstat-aix.txt
Normal file
|
@ -0,0 +1,157 @@
|
||||||
|
icmp:
|
||||||
|
12 calls to icmp_error
|
||||||
|
0 errors not generated because old message was icmp
|
||||||
|
Output histogram:
|
||||||
|
destination unreachable: 12
|
||||||
|
0 messages with bad code fields
|
||||||
|
0 messages < minimum length
|
||||||
|
0 bad checksums
|
||||||
|
0 messages with bad length
|
||||||
|
Input histogram:
|
||||||
|
destination unreachable: 3
|
||||||
|
0 message responses generated
|
||||||
|
igmp:
|
||||||
|
0 messages received
|
||||||
|
0 messages received with too few bytes
|
||||||
|
0 messages received with bad checksum
|
||||||
|
0 membership queries received
|
||||||
|
0 membership queries received with invalid field(s)
|
||||||
|
0 membership reports received
|
||||||
|
0 membership reports received with invalid field(s)
|
||||||
|
0 membership reports received for groups to which we belong
|
||||||
|
2 membership reports sent
|
||||||
|
tcp:
|
||||||
|
31274 packets sent
|
||||||
|
27328 data packets (82928168 bytes)
|
||||||
|
86 data packets (108992 bytes) retransmitted
|
||||||
|
2938 ack-only packets (2698 delayed)
|
||||||
|
0 URG only packets
|
||||||
|
0 window probe packets
|
||||||
|
784 window update packets
|
||||||
|
138 control packets
|
||||||
|
3812 large sends
|
||||||
|
74913716 bytes sent using largesend
|
||||||
|
64069 bytes is the biggest largesend
|
||||||
|
39830 packets received
|
||||||
|
22701 acks (for 82928732 bytes)
|
||||||
|
112 duplicate acks
|
||||||
|
0 acks for unsent data
|
||||||
|
15579 packets (5876585 bytes) received in-sequence
|
||||||
|
62 completely duplicate packets (320 bytes)
|
||||||
|
57 old duplicate packets
|
||||||
|
0 packets with some dup. data (0 bytes duped)
|
||||||
|
75 out-of-order packets (6408 bytes)
|
||||||
|
0 packets (0 bytes) of data after window
|
||||||
|
0 window probes
|
||||||
|
1723 window update packets
|
||||||
|
0 packets received after close
|
||||||
|
0 packets with bad hardware assisted checksum
|
||||||
|
0 discarded for bad checksums
|
||||||
|
0 discarded for bad header offset fields
|
||||||
|
0 discarded because packet too short
|
||||||
|
1 discarded by listeners
|
||||||
|
0 discarded due to listener's queue full
|
||||||
|
3207 ack packet headers correctly predicted
|
||||||
|
15050 data packet headers correctly predicted
|
||||||
|
63 connection requests
|
||||||
|
23 connection accepts
|
||||||
|
85 connections established (including accepts)
|
||||||
|
114 connections closed (including 0 drops)
|
||||||
|
0 connections with ECN capability
|
||||||
|
0 times responded to ECN
|
||||||
|
0 embryonic connections dropped
|
||||||
|
20314 segments updated rtt (of 16791 attempts)
|
||||||
|
0 segments with congestion window reduced bit set
|
||||||
|
0 segments with congestion experienced bit set
|
||||||
|
0 resends due to path MTU discovery
|
||||||
|
2 path MTU discovery terminations due to retransmits
|
||||||
|
25 retransmit timeouts
|
||||||
|
0 connections dropped by rexmit timeout
|
||||||
|
4 fast retransmits
|
||||||
|
1 when congestion window less than 4 segments
|
||||||
|
28 newreno retransmits
|
||||||
|
4 times avoided false fast retransmits
|
||||||
|
0 persist timeouts
|
||||||
|
0 connections dropped due to persist timeout
|
||||||
|
0 keepalive timeouts
|
||||||
|
0 keepalive probes sent
|
||||||
|
0 connections dropped by keepalive
|
||||||
|
0 times SACK blocks array is extended
|
||||||
|
0 times SACK holes array is extended
|
||||||
|
0 packets dropped due to memory allocation failure
|
||||||
|
0 connections in timewait reused
|
||||||
|
0 delayed ACKs for SYN
|
||||||
|
0 delayed ACKs for FIN
|
||||||
|
0 send_and_disconnects
|
||||||
|
0 spliced connections
|
||||||
|
0 spliced connections closed
|
||||||
|
0 spliced connections reset
|
||||||
|
0 spliced connections timeout
|
||||||
|
0 spliced connections persist timeout
|
||||||
|
0 spliced connections keepalive timeout
|
||||||
|
0 TCP checksum offload disabled during retransmit
|
||||||
|
0 Connections dropped due to bad ACKs
|
||||||
|
0 Connections dropped due to duplicate SYN packets
|
||||||
|
0 fastpath loopback connections
|
||||||
|
0 fastpath loopback sent packets (0 bytes)
|
||||||
|
0 fastpath loopback received packets (0 bytes)
|
||||||
|
0 fake SYN segments dropped
|
||||||
|
0 fake RST segments dropped
|
||||||
|
0 data injection segments dropped
|
||||||
|
0 TCPTR maximum connections dropped
|
||||||
|
0 TCPTR connections dropped for no memory
|
||||||
|
0 TCPTR maximum per host connections dropped
|
||||||
|
0 connections dropped due to max assembly queue depth
|
||||||
|
udp:
|
||||||
|
34559 datagrams received
|
||||||
|
0 incomplete headers
|
||||||
|
0 bad data length fields
|
||||||
|
0 bad checksums
|
||||||
|
1849 dropped due to no socket
|
||||||
|
8218 broadcast/multicast datagrams dropped due to no socket
|
||||||
|
0 socket buffer overflows
|
||||||
|
24492 delivered
|
||||||
|
26332 datagrams output
|
||||||
|
ip:
|
||||||
|
76229 total packets received
|
||||||
|
0 bad header checksums
|
||||||
|
0 with size smaller than minimum
|
||||||
|
0 with data size < data length
|
||||||
|
0 with header length < data size
|
||||||
|
0 with data length < header length
|
||||||
|
0 with bad options
|
||||||
|
0 with incorrect version number
|
||||||
|
0 fragments received
|
||||||
|
0 fragments dropped (dup or out of space)
|
||||||
|
0 fragments dropped after timeout
|
||||||
|
0 packets reassembled ok
|
||||||
|
72552 packets for this host
|
||||||
|
3 packets for unknown/unsupported protocol
|
||||||
|
24 packets forwarded
|
||||||
|
0 packets not forwardable
|
||||||
|
0 redirects sent
|
||||||
|
55784 packets sent from this host
|
||||||
|
0 packets sent with fabricated ip header
|
||||||
|
0 output packets dropped due to no bufs, etc.
|
||||||
|
0 output packets discarded due to no route
|
||||||
|
0 output datagrams fragmented
|
||||||
|
0 fragments created
|
||||||
|
0 datagrams that can't be fragmented
|
||||||
|
0 IP Multicast packets dropped due to no receiver
|
||||||
|
0 successful path MTU discovery cycles
|
||||||
|
0 path MTU rediscovery cycles attempted
|
||||||
|
0 path MTU discovery no-response estimates
|
||||||
|
0 path MTU discovery response timeouts
|
||||||
|
0 path MTU discovery decreases detected
|
||||||
|
0 path MTU discovery packets sent
|
||||||
|
0 path MTU discovery memory allocation failures
|
||||||
|
0 ipintrq overflows
|
||||||
|
0 with illegal source
|
||||||
|
0 packets processed by threads
|
||||||
|
0 packets dropped by threads
|
||||||
|
0 packets dropped due to the full socket receive buffer
|
||||||
|
0 dead gateway detection packets sent
|
||||||
|
0 dead gateway detection packet allocation failures
|
||||||
|
0 dead gateway detection gateway allocation failures
|
||||||
|
0 incoming packets dropped due to MLS filters
|
||||||
|
0 packets not sent due to MLS filters
|
|
@ -1,6 +0,0 @@
|
||||||
Unit: KB
|
|
||||||
------------------------------------------------------------------------
|
|
||||||
Memory
|
|
||||||
------------------------------------------------------------------------
|
|
||||||
Size Inuse Free Pin Virtual Available Pgsp
|
|
||||||
4194304 4065060 129244 1878240 2784988 1058012 524288
|
|
|
@ -1,7 +0,0 @@
|
||||||
|
|
||||||
System configuration: lcpu=8 mem=4096MB ent=0.50
|
|
||||||
|
|
||||||
kthr memory page faults cpu time
|
|
||||||
----------- --------------------- ------------------------------------ ------------------ ----------------------- --------
|
|
||||||
r b p avm fre fi fo pi po fr sr in sy cs us sy id wa pc ec hr mi se
|
|
||||||
2 1 0 633739 130144 0 13 0 0 2 2 7 969 529 0 0 99 0 0.00 0.1 07:53:28
|
|
36
plugins/os-base/README.md
Normal file
36
plugins/os-base/README.md
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
# Base Plugin
|
||||||
|
|
||||||
|
## Processor Extension
|
||||||
|
|
||||||
|
Reports the following metrics seen:
|
||||||
|
|
||||||
|
- **user** - CPU time spend on user processes.
|
||||||
|
- **system** -CPU time spend on system processes.
|
||||||
|
- **iowait** - CPU time spend on waiting (for i/o).
|
||||||
|
- **idle** - CPU time spend on idle (doing nothing).
|
||||||
|
- **busy** - CPU time not spend on idle (working).
|
||||||
|
|
||||||
|
|
||||||
|
## Memory Extension
|
||||||
|
|
||||||
|
Reports the following metrics, from the *free* command:
|
||||||
|
|
||||||
|
- **total** - The total amount of (installed) memory (in KB).
|
||||||
|
- **used** - Used memory (calculated as total - free - buffers - cache) (in KB).
|
||||||
|
- **free** - Unused memory (MemFree and SwapFree in /proc/meminfo) (in KB).
|
||||||
|
- **shared** - Memory used (mostly) by tmpfs (Shmem in /proc/meminfo) (in KB).
|
||||||
|
- **buffers** - Sum of buffers and cache (in KB).
|
||||||
|
- **available** - Estimation of how much memory is available for starting new applications, without swapping (in KB).
|
||||||
|
- **usage** - Percentage of memory used out of the total amount of memory.
|
||||||
|
|
||||||
|
|
||||||
|
## Disk Extension
|
||||||
|
|
||||||
|
|
||||||
|
Only reports first device found. Improvements on the TODO.
|
||||||
|
|
||||||
|
Metrics reported are:
|
||||||
|
|
||||||
|
- **device** - Name of device.
|
||||||
|
- **reads** - The total number of KB read.
|
||||||
|
- **writes** - The total number of KB written.
|
2
plugins/os-base/build.gradle
Normal file
2
plugins/os-base/build.gradle
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
plugins {
|
||||||
|
}
|
7
plugins/os-base/gradle.properties
Normal file
7
plugins/os-base/gradle.properties
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
pluginId=sysmon-base
|
||||||
|
pluginClass=sysmon.plugins.os_base.BasePlugin
|
||||||
|
pluginVersion=0.0.1
|
||||||
|
pluginProvider=System Monitor
|
||||||
|
pluginDependencies=
|
||||||
|
pluginDescription=Base OS metrics where supported.
|
||||||
|
|
|
@ -0,0 +1,79 @@
|
||||||
|
package sysmon.plugins.os_base;
|
||||||
|
|
||||||
|
import org.pf4j.Extension;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import oshi.SystemInfo;
|
||||||
|
import oshi.hardware.HWDiskStore;
|
||||||
|
import oshi.hardware.HardwareAbstractionLayer;
|
||||||
|
import sysmon.shared.Measurement;
|
||||||
|
import sysmon.shared.MetricExtension;
|
||||||
|
import sysmon.shared.MetricResult;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Extension
|
||||||
|
public class BaseDiskExtension implements MetricExtension {
|
||||||
|
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(BaseDiskExtension.class);
|
||||||
|
|
||||||
|
private HardwareAbstractionLayer hardwareAbstractionLayer;
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isSupported() {
|
||||||
|
hardwareAbstractionLayer = BasePlugin.getHardwareAbstractionLayer();
|
||||||
|
return hardwareAbstractionLayer != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "base-disk";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getProvides() {
|
||||||
|
return "disk";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDescription() {
|
||||||
|
return "Base Disk Metrics";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MetricResult getMetrics() {
|
||||||
|
|
||||||
|
long writeBytes = 0L;
|
||||||
|
long readBytes = 0L;
|
||||||
|
long transferTime = 0L;
|
||||||
|
long queueLength = 0L;
|
||||||
|
|
||||||
|
Map<String, String> tagsMap = new HashMap<>();
|
||||||
|
Map<String, Object> fieldsMap = new HashMap<>();
|
||||||
|
|
||||||
|
List<HWDiskStore> diskStores = hardwareAbstractionLayer.getDiskStores();
|
||||||
|
for(HWDiskStore store : diskStores) {
|
||||||
|
String name = store.getName();
|
||||||
|
if (name.matches("hdisk[0-9]+") || name.matches("/dev/[sv]d[a-z]{1}") || name.matches("/dev/nvme[0-9]n[0-9]")) {
|
||||||
|
log.debug("Using device: " + name);
|
||||||
|
writeBytes += store.getWriteBytes();
|
||||||
|
readBytes += store.getReadBytes();
|
||||||
|
transferTime += store.getTransferTime();
|
||||||
|
queueLength = store.getCurrentQueueLength();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldsMap.put("reads", readBytes);
|
||||||
|
fieldsMap.put("writes", writeBytes);
|
||||||
|
fieldsMap.put("iotime", transferTime);
|
||||||
|
fieldsMap.put("queue", queueLength);
|
||||||
|
|
||||||
|
log.debug(fieldsMap.toString());
|
||||||
|
return new MetricResult("disk", new Measurement(tagsMap, fieldsMap));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,64 @@
|
||||||
|
package sysmon.plugins.os_base;
|
||||||
|
|
||||||
|
import org.pf4j.Extension;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import oshi.SystemInfo;
|
||||||
|
import oshi.hardware.HardwareAbstractionLayer;
|
||||||
|
import sysmon.shared.Measurement;
|
||||||
|
import sysmon.shared.MetricExtension;
|
||||||
|
import sysmon.shared.MetricResult;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Extension
|
||||||
|
public class BaseMemoryExtension implements MetricExtension {
|
||||||
|
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(BaseMemoryExtension.class);
|
||||||
|
|
||||||
|
private HardwareAbstractionLayer hardwareAbstractionLayer;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isSupported() {
|
||||||
|
hardwareAbstractionLayer = BasePlugin.getHardwareAbstractionLayer();
|
||||||
|
return hardwareAbstractionLayer != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "base-memory";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getProvides() {
|
||||||
|
return "memory";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDescription() {
|
||||||
|
return "Base Memory Metrics";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MetricResult getMetrics() {
|
||||||
|
|
||||||
|
Map<String, String> tagsMap = new HashMap<>();
|
||||||
|
Map<String, Object> fieldsMap = new HashMap<>();
|
||||||
|
|
||||||
|
long total = hardwareAbstractionLayer.getMemory().getTotal();
|
||||||
|
long available = hardwareAbstractionLayer.getMemory().getAvailable();
|
||||||
|
float usage = ((float) (total - available) / total ) * 100;
|
||||||
|
|
||||||
|
fieldsMap.put("available", available);
|
||||||
|
fieldsMap.put("total", total);
|
||||||
|
fieldsMap.put("usage", usage);
|
||||||
|
fieldsMap.put("paged", hardwareAbstractionLayer.getMemory().getPageSize());
|
||||||
|
fieldsMap.put("virtual", hardwareAbstractionLayer.getMemory().getVirtualMemory().getVirtualInUse());
|
||||||
|
|
||||||
|
log.debug(fieldsMap.toString());
|
||||||
|
return new MetricResult("memory", new Measurement(tagsMap, fieldsMap));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,81 @@
|
||||||
|
package sysmon.plugins.os_base;
|
||||||
|
|
||||||
|
import org.pf4j.Extension;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import oshi.SystemInfo;
|
||||||
|
import oshi.hardware.HardwareAbstractionLayer;
|
||||||
|
import oshi.hardware.NetworkIF;
|
||||||
|
import sysmon.shared.Measurement;
|
||||||
|
import sysmon.shared.MetricExtension;
|
||||||
|
import sysmon.shared.MetricResult;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Extension
|
||||||
|
public class BaseNetworkExtension implements MetricExtension {
|
||||||
|
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(BaseNetworkExtension.class);
|
||||||
|
|
||||||
|
private HardwareAbstractionLayer hardwareAbstractionLayer;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isSupported() {
|
||||||
|
hardwareAbstractionLayer = BasePlugin.getHardwareAbstractionLayer();
|
||||||
|
return hardwareAbstractionLayer != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "base-network";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getProvides() {
|
||||||
|
return "network";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDescription() {
|
||||||
|
return "Base Network Metrics";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MetricResult getMetrics() {
|
||||||
|
|
||||||
|
long rxBytes = 0L;
|
||||||
|
long rxPackets = 0L;
|
||||||
|
long rxErrs = 0L;
|
||||||
|
long txBytes = 0L;
|
||||||
|
long txPackets = 0L;
|
||||||
|
long txErrs = 0L;
|
||||||
|
|
||||||
|
Map<String, String> tagsMap = new HashMap<>();
|
||||||
|
Map<String, Object> fieldsMap = new HashMap<>();
|
||||||
|
|
||||||
|
List<NetworkIF> interfaces = hardwareAbstractionLayer.getNetworkIFs();
|
||||||
|
for(NetworkIF netif : interfaces) {
|
||||||
|
//String name = netif.getName();
|
||||||
|
//log.warn("Device: " + name);
|
||||||
|
rxPackets += netif.getPacketsRecv();
|
||||||
|
txPackets += netif.getPacketsSent();
|
||||||
|
rxBytes += netif.getBytesRecv();
|
||||||
|
txBytes += netif.getBytesSent();
|
||||||
|
rxErrs += netif.getInErrors();
|
||||||
|
txErrs += netif.getOutErrors();
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldsMap.put("rxPackets", rxPackets);
|
||||||
|
fieldsMap.put("txPackets", txPackets);
|
||||||
|
fieldsMap.put("rxBytes", rxBytes);
|
||||||
|
fieldsMap.put("txBytes", txBytes);
|
||||||
|
fieldsMap.put("rxErrors", rxErrs);
|
||||||
|
fieldsMap.put("txErrors", txErrs);
|
||||||
|
|
||||||
|
log.debug(fieldsMap.toString());
|
||||||
|
return new MetricResult("network", new Measurement(tagsMap, fieldsMap));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
package sysmon.plugins.os_base;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.pf4j.Plugin;
|
||||||
|
import org.pf4j.PluginWrapper;
|
||||||
|
import oshi.SystemInfo;
|
||||||
|
import oshi.hardware.HardwareAbstractionLayer;
|
||||||
|
|
||||||
|
|
||||||
|
public class BasePlugin extends Plugin {
|
||||||
|
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(BasePlugin.class);
|
||||||
|
|
||||||
|
private static SystemInfo systemInfo;
|
||||||
|
private static HardwareAbstractionLayer hardwareAbstractionLayer;
|
||||||
|
|
||||||
|
public BasePlugin(PluginWrapper wrapper) {
|
||||||
|
super(wrapper);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HardwareAbstractionLayer getHardwareAbstractionLayer() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
if(systemInfo == null) {
|
||||||
|
systemInfo = new SystemInfo();
|
||||||
|
}
|
||||||
|
if(hardwareAbstractionLayer == null) {
|
||||||
|
hardwareAbstractionLayer = systemInfo.getHardware();
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (UnsupportedOperationException e) {
|
||||||
|
log.warn(e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
return hardwareAbstractionLayer;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,94 @@
|
||||||
|
package sysmon.plugins.os_base;
|
||||||
|
|
||||||
|
import org.pf4j.Extension;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import oshi.SystemInfo;
|
||||||
|
import oshi.hardware.CentralProcessor;
|
||||||
|
import oshi.hardware.HardwareAbstractionLayer;
|
||||||
|
import sysmon.shared.Measurement;
|
||||||
|
import sysmon.shared.MetricExtension;
|
||||||
|
import sysmon.shared.MetricResult;
|
||||||
|
|
||||||
|
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.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Extension
|
||||||
|
public class BaseProcessorExtension implements MetricExtension {
|
||||||
|
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(BaseProcessorExtension.class);
|
||||||
|
|
||||||
|
private HardwareAbstractionLayer hardwareAbstractionLayer;
|
||||||
|
private long[] oldTicks;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isSupported() {
|
||||||
|
hardwareAbstractionLayer = BasePlugin.getHardwareAbstractionLayer();
|
||||||
|
return hardwareAbstractionLayer != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "base-processor";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getProvides() {
|
||||||
|
return "processor";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDescription() {
|
||||||
|
return "Base Processor Metrics";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MetricResult getMetrics() {
|
||||||
|
|
||||||
|
Map<String, String> tagsMap = new HashMap<>();
|
||||||
|
Map<String, Object> fieldsMap = new HashMap<>();
|
||||||
|
|
||||||
|
long[] ticks = hardwareAbstractionLayer.getProcessor().getSystemCpuLoadTicks();
|
||||||
|
if(oldTicks == null || oldTicks.length != ticks.length) {
|
||||||
|
oldTicks = ticks;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
long nice = ticks[CentralProcessor.TickType.NICE.getIndex()] - oldTicks[CentralProcessor.TickType.NICE.getIndex()];
|
||||||
|
long user = ticks[CentralProcessor.TickType.USER.getIndex()] - oldTicks[CentralProcessor.TickType.USER.getIndex()];
|
||||||
|
long system = ticks[CentralProcessor.TickType.SYSTEM.getIndex()] - oldTicks[CentralProcessor.TickType.SYSTEM.getIndex()];
|
||||||
|
long steal = ticks[CentralProcessor.TickType.STEAL.getIndex()] - oldTicks[CentralProcessor.TickType.STEAL.getIndex()];
|
||||||
|
long irq = ticks[CentralProcessor.TickType.IRQ.getIndex()] - oldTicks[CentralProcessor.TickType.IRQ.getIndex()];
|
||||||
|
long softirq = ticks[CentralProcessor.TickType.SOFTIRQ.getIndex()] - oldTicks[CentralProcessor.TickType.SOFTIRQ.getIndex()];
|
||||||
|
long idle = ticks[CentralProcessor.TickType.IDLE.getIndex()] - oldTicks[CentralProcessor.TickType.IDLE.getIndex()];
|
||||||
|
long iowait = ticks[CentralProcessor.TickType.IOWAIT.getIndex()] - oldTicks[CentralProcessor.TickType.IOWAIT.getIndex()];
|
||||||
|
|
||||||
|
long busy = nice + user + system + steal + irq + softirq;
|
||||||
|
long nonBusy = idle + iowait;
|
||||||
|
long total = busy + nonBusy;
|
||||||
|
|
||||||
|
fieldsMap.put("system", ((float) system / (float) total) * 100);
|
||||||
|
fieldsMap.put("user", ((float) user / (float) total) * 100);
|
||||||
|
fieldsMap.put("nice", ((float) nice / (float) total) * 100);
|
||||||
|
fieldsMap.put("iowait", ((float) iowait / (float) total) * 100);
|
||||||
|
fieldsMap.put("steal", ((float) steal / (float) total) * 100);
|
||||||
|
fieldsMap.put("irq", ((float) irq / (float) total) * 100);
|
||||||
|
fieldsMap.put("softirq", ((float) softirq / (float) total) * 100);
|
||||||
|
fieldsMap.put("idle", ((float) idle / (float) total) * 100);
|
||||||
|
fieldsMap.put("busy", ((float) busy / (float) total) * 100);
|
||||||
|
|
||||||
|
oldTicks = ticks;
|
||||||
|
log.debug(fieldsMap.toString());
|
||||||
|
return new MetricResult("processor", new Measurement(tagsMap, fieldsMap));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
6
plugins/os-base/src/test/resources/proc_net_sockstat.txt
Normal file
6
plugins/os-base/src/test/resources/proc_net_sockstat.txt
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
sockets: used 1238
|
||||||
|
TCP: inuse 52 orphan 0 tw 18 alloc 55 mem 7
|
||||||
|
UDP: inuse 11 mem 10
|
||||||
|
UDPLITE: inuse 0
|
||||||
|
RAW: inuse 0
|
||||||
|
FRAG: inuse 0 memory 0
|
|
@ -0,0 +1,44 @@
|
||||||
|
package sysmon.plugins.os_ibmi;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import sysmon.shared.MetricExtension;
|
||||||
|
import sysmon.shared.MetricResult;
|
||||||
|
|
||||||
|
public class TestExtension implements MetricExtension {
|
||||||
|
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(TestExtension.class);
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isSupported() {
|
||||||
|
|
||||||
|
String osArch = System.getProperty("os.arch").toLowerCase();
|
||||||
|
String osName = System.getProperty("os.name").toLowerCase();
|
||||||
|
|
||||||
|
System.err.println("OS Arch: " + osArch);
|
||||||
|
System.err.println("OS Name: " + osName);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "ibmi-test";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getProvides() {
|
||||||
|
return "test";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDescription() {
|
||||||
|
return "IBM i Test Extension";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MetricResult getMetrics() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,14 +1,14 @@
|
||||||
# Linux Plugin
|
# Base Plugin
|
||||||
|
|
||||||
## Processor Extension
|
## Processor Extension
|
||||||
|
|
||||||
Reports the following metrics seen:
|
Reports the following metrics seen:
|
||||||
|
|
||||||
- **user** - Percentage of CPU time spend on user processes.
|
- **user** - CPU time spend on user processes.
|
||||||
- **sys** - Percentage of CPU time spend on system processes.
|
- **system** -CPU time spend on system processes.
|
||||||
- **wait** - Percentage of CPU time spend on waiting (for i/o).
|
- **iowait** - CPU time spend on waiting (for i/o).
|
||||||
- **idle** - Percentage of CPU time spend on idle (doing nothing).
|
- **idle** - CPU time spend on idle (doing nothing).
|
||||||
- **busy** - Percentage of CPU time not spend on idle (working).
|
- **busy** - CPU time not spend on idle (working).
|
||||||
|
|
||||||
|
|
||||||
## Memory Extension
|
## Memory Extension
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
pluginId=sysmon-linux
|
pluginId=sysmon-linux
|
||||||
pluginClass=sysmon.plugins.os_linux.LinuxPlugin
|
pluginClass=sysmon.plugins.os_linux.LinuxPlugin
|
||||||
pluginVersion=0.0.1
|
|
||||||
pluginProvider=System Monitor
|
|
||||||
pluginDependencies=
|
pluginDependencies=
|
||||||
pluginDescription=Collects Linux OS metrics.
|
pluginDescription=Linux OS Metrics.
|
||||||
|
|
||||||
|
|
|
@ -1,88 +0,0 @@
|
||||||
package sysmon.plugins.os_linux;
|
|
||||||
|
|
||||||
import org.pf4j.Extension;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import sysmon.shared.Measurement;
|
|
||||||
import sysmon.shared.MetricExtension;
|
|
||||||
import sysmon.shared.MetricResult;
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
@Extension
|
|
||||||
public class LinuxDiskExtension implements MetricExtension {
|
|
||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(LinuxDiskExtension.class);
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isSupported() {
|
|
||||||
return System.getProperty("os.name").toLowerCase().contains("linux");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getName() {
|
|
||||||
return "linux-disk";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getProvides() {
|
|
||||||
return "disk";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getDescription() {
|
|
||||||
return "Linux Disk Metrics";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MetricResult getMetrics() {
|
|
||||||
|
|
||||||
LinuxDiskProcLine proc1 = processFileOutput(readProcFile());
|
|
||||||
try {
|
|
||||||
Thread.sleep(1 * 1000); // TODO: Configure sample collect time
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
log.warn("getMetrics() - sleep interrupted");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
LinuxDiskProcLine proc2 = processFileOutput(readProcFile());
|
|
||||||
|
|
||||||
LinuxDiskStat stat = new LinuxDiskStat(proc1, proc2);
|
|
||||||
return new MetricResult("disk", new Measurement(stat.getTags(), stat.getFields()));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
protected List<String> readProcFile() {
|
|
||||||
|
|
||||||
List<String> allLines = new ArrayList<>();
|
|
||||||
try {
|
|
||||||
allLines = Files.readAllLines(Paths.get("/proc/diskstats"), StandardCharsets.UTF_8);
|
|
||||||
} catch (IOException e) {
|
|
||||||
log.error(e.getMessage());
|
|
||||||
}
|
|
||||||
return allLines;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
protected LinuxDiskProcLine processFileOutput(List<String> inputLines) {
|
|
||||||
|
|
||||||
List<String> lines = new ArrayList<>(inputLines.size());
|
|
||||||
for(String line : inputLines) {
|
|
||||||
String[] splitStr = line.trim().split("\\s+");
|
|
||||||
String device = splitStr[2];
|
|
||||||
if (device.matches("[sv]d[a-z]{1}") || device.matches("nvme[0-9]n[0-9]")) {
|
|
||||||
//log.warn("Going for: " + line);
|
|
||||||
lines.add(line);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return new LinuxDiskProcLine(lines);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,146 +0,0 @@
|
||||||
package sysmon.plugins.os_linux;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class LinuxDiskProcLine {
|
|
||||||
|
|
||||||
// Sectors to bytes - each sector is 512 bytes - https://lkml.org/lkml/2015/8/17/269
|
|
||||||
private static final int SECTOR_BYTE_SIZE = 512;
|
|
||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(LinuxDiskProcLine.class);
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
== ===================================
|
|
||||||
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 long readsCompleted; // successfully
|
|
||||||
//private long readsMerged;
|
|
||||||
private long sectorsRead; // 512 bytes pr. sector
|
|
||||||
private long timeSpentReading; // ms
|
|
||||||
private long writesCompleted; // successfully
|
|
||||||
//private long writesMerged;
|
|
||||||
private long sectorsWritten; // 512 bytes pr. sector
|
|
||||||
private long timeSpentWriting; // ms
|
|
||||||
//private long ioInProgress;
|
|
||||||
private long timeSpentOnIo; // ms
|
|
||||||
//private long timeSpentOnIoWeighted;
|
|
||||||
|
|
||||||
//private long discardsCompleted; // successfully
|
|
||||||
//private long discardsMerged;
|
|
||||||
//private long sectorsDiscarded; // 512 bytes pr. sector
|
|
||||||
//private long timeSpentDiscarding; // ms
|
|
||||||
|
|
||||||
//private long flushRequestsCompleted;
|
|
||||||
//private long timeSpentFlushing; // ms
|
|
||||||
|
|
||||||
|
|
||||||
public LinuxDiskProcLine(List<String> procLines) {
|
|
||||||
|
|
||||||
for(String procLine : procLines) {
|
|
||||||
|
|
||||||
String[] splitStr = procLine.trim().split("\\s+");
|
|
||||||
if (splitStr.length < 14) {
|
|
||||||
throw new UnsupportedOperationException("Linux proc DISK string error: " + procLine);
|
|
||||||
}
|
|
||||||
|
|
||||||
//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 Long getTimeSpentOnIo() {
|
|
||||||
return timeSpentOnIo;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Long getBytesRead() {
|
|
||||||
return sectorsRead * SECTOR_BYTE_SIZE;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Long getBytesWritten() {
|
|
||||||
return sectorsWritten * SECTOR_BYTE_SIZE;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Long getTimeSpentReading() {
|
|
||||||
return timeSpentReading;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Long getTimeSpentWriting() {
|
|
||||||
return timeSpentWriting;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Long getTransactions() {
|
|
||||||
return readsCompleted + writesCompleted;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,39 +0,0 @@
|
||||||
package sysmon.plugins.os_linux;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public class LinuxDiskStat {
|
|
||||||
|
|
||||||
private String device;
|
|
||||||
private final long iotime;
|
|
||||||
private final long reads;
|
|
||||||
private final long writes;
|
|
||||||
private final long kbps;
|
|
||||||
private final long tps;
|
|
||||||
|
|
||||||
LinuxDiskStat(LinuxDiskProcLine proc1, LinuxDiskProcLine proc2) {
|
|
||||||
iotime = proc2.getTimeSpentOnIo() - proc1.getTimeSpentOnIo();
|
|
||||||
writes = proc2.getBytesWritten() - proc1.getBytesWritten();
|
|
||||||
reads = proc2.getBytesRead() - proc1.getBytesRead();
|
|
||||||
kbps = (writes + reads) / 1024;
|
|
||||||
tps = proc2.getTransactions() - proc1.getTransactions();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<String, String> getTags() {
|
|
||||||
return new HashMap<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<String, Object> getFields() {
|
|
||||||
Map<String, Object> fields = new HashMap<>();
|
|
||||||
fields.put("iotime", iotime);
|
|
||||||
fields.put("writes", writes);
|
|
||||||
fields.put("reads", reads);
|
|
||||||
fields.put("kbps", kbps);
|
|
||||||
fields.put("tps", tps);
|
|
||||||
return fields;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,67 +0,0 @@
|
||||||
package sysmon.plugins.os_linux;
|
|
||||||
|
|
||||||
import org.pf4j.Extension;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import sysmon.shared.Measurement;
|
|
||||||
import sysmon.shared.MetricExtension;
|
|
||||||
import sysmon.shared.MetricResult;
|
|
||||||
import sysmon.shared.PluginHelper;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
@Extension
|
|
||||||
public class LinuxMemoryExtension implements MetricExtension {
|
|
||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(LinuxMemoryExtension.class);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isSupported() {
|
|
||||||
|
|
||||||
if(!System.getProperty("os.name").toLowerCase().contains("linux")) {
|
|
||||||
log.warn("Requires Linux.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!PluginHelper.canExecute("free")) {
|
|
||||||
log.warn("Requires the 'free' command.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getName() {
|
|
||||||
return "linux-memory";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getProvides() {
|
|
||||||
return "memory";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getDescription() {
|
|
||||||
return "Linux Memory Metrics";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MetricResult getMetrics() {
|
|
||||||
|
|
||||||
List<String> svmon = PluginHelper.executeCommand("free -k");
|
|
||||||
LinuxMemoryStat memoryStat = processCommandOutput(svmon);
|
|
||||||
|
|
||||||
Map<String, String> tagsMap = memoryStat.getTags();
|
|
||||||
Map<String, Object> fieldsMap = memoryStat.getFields();
|
|
||||||
|
|
||||||
return new MetricResult("memory", new Measurement(tagsMap, fieldsMap));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected LinuxMemoryStat processCommandOutput(List<String> inputLines) {
|
|
||||||
return new LinuxMemoryStat(inputLines);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,63 +0,0 @@
|
||||||
package sysmon.plugins.os_linux;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.regex.Matcher;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
public class LinuxMemoryStat {
|
|
||||||
|
|
||||||
/*
|
|
||||||
total used free shared buff/cache available
|
|
||||||
Mem: 16069172 5896832 4597860 639780 5574480 9192992
|
|
||||||
Swap: 3985404 0 3985404
|
|
||||||
*/
|
|
||||||
private static final Pattern pattern = Pattern.compile("^Mem:\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)");
|
|
||||||
|
|
||||||
private long total;
|
|
||||||
private long used;
|
|
||||||
private long free;
|
|
||||||
private long shared;
|
|
||||||
private long buffers;
|
|
||||||
private long available;
|
|
||||||
//private String mode;
|
|
||||||
|
|
||||||
LinuxMemoryStat(List<String> lines) {
|
|
||||||
for (String line : lines) {
|
|
||||||
Matcher matcher = pattern.matcher(line);
|
|
||||||
if (matcher.find() && matcher.groupCount() == 6) {
|
|
||||||
total = Long.parseLong(matcher.group(1));
|
|
||||||
used = Long.parseLong(matcher.group(2));
|
|
||||||
free = Long.parseLong(matcher.group(3));
|
|
||||||
shared = Long.parseLong(matcher.group(4));
|
|
||||||
buffers = Long.parseLong(matcher.group(5));
|
|
||||||
available = Long.parseLong(matcher.group(6));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public Map<String, String> getTags() {
|
|
||||||
return new HashMap<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public Map<String, Object> getFields() {
|
|
||||||
|
|
||||||
float usage = ((float) (total - available) / total ) * 100;
|
|
||||||
//BigDecimal usage = new BigDecimal(tmp).setScale(2, RoundingMode.HALF_UP);
|
|
||||||
|
|
||||||
Map<String, Object> fields = new HashMap<>();
|
|
||||||
fields.put("total", total);
|
|
||||||
fields.put("used", used);
|
|
||||||
fields.put("free", free);
|
|
||||||
fields.put("shared", shared);
|
|
||||||
fields.put("buffers", buffers);
|
|
||||||
fields.put("available", available);
|
|
||||||
fields.put("usage", usage);
|
|
||||||
return fields;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -0,0 +1,74 @@
|
||||||
|
package sysmon.plugins.os_linux;
|
||||||
|
|
||||||
|
import org.pf4j.Extension;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import sysmon.shared.Measurement;
|
||||||
|
import sysmon.shared.MetricExtension;
|
||||||
|
import sysmon.shared.MetricResult;
|
||||||
|
import sysmon.shared.PluginHelper;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
// Disabled
|
||||||
|
//@Extension
|
||||||
|
public class LinuxNetstatExtension implements MetricExtension {
|
||||||
|
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(LinuxNetstatExtension.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isSupported() {
|
||||||
|
|
||||||
|
if(!System.getProperty("os.name").toLowerCase().contains("linux")) {
|
||||||
|
log.warn("Requires Linux.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!PluginHelper.canExecute("netstat")) {
|
||||||
|
log.warn("Requires the 'netstat' command.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "linux-network-netstat";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getProvides() {
|
||||||
|
return "network-netstat";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDescription() {
|
||||||
|
return "Linux Netstat Metrics";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MetricResult getMetrics() throws Exception {
|
||||||
|
|
||||||
|
Map<String, String> tagsMap = null;
|
||||||
|
Map<String, Object> fieldsMap = null;
|
||||||
|
|
||||||
|
try (InputStream inputStream = PluginHelper.executeCommand("netstat -s")) {
|
||||||
|
LinuxNetstatParser parser = processCommandOutput(inputStream);
|
||||||
|
tagsMap = parser.getTags();
|
||||||
|
fieldsMap = parser.getFields();
|
||||||
|
}
|
||||||
|
|
||||||
|
log.debug(fieldsMap.toString());
|
||||||
|
return new MetricResult("network_netstat", new Measurement(tagsMap, fieldsMap));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected LinuxNetstatParser processCommandOutput(InputStream input) throws IOException {
|
||||||
|
return new LinuxNetstatParser(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,168 @@
|
||||||
|
package sysmon.plugins.os_linux;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class LinuxNetstatParser {
|
||||||
|
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(LinuxNetstatParser.class);
|
||||||
|
|
||||||
|
private long ipTotalPacketsReceived;
|
||||||
|
private long ipForwarded;
|
||||||
|
private long ipIncomingPacketsDiscarded;
|
||||||
|
private long ipOutgoingPacketsDropped;
|
||||||
|
|
||||||
|
private long tcpConnectionsEstablished;
|
||||||
|
private long tcpSegmentsReceived;
|
||||||
|
private long tcpSegmentsSent;
|
||||||
|
|
||||||
|
private long udpPacketsReceived;
|
||||||
|
private long udpPacketsSent;
|
||||||
|
|
||||||
|
|
||||||
|
public LinuxNetstatParser(InputStream inputStream) throws IOException {
|
||||||
|
|
||||||
|
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
|
||||||
|
while (reader.ready()) {
|
||||||
|
String line = reader.readLine();
|
||||||
|
log.debug("LinuxNetstatParser() - Line: " + line);
|
||||||
|
|
||||||
|
if(line.startsWith("Ip:")) {
|
||||||
|
parseIp(reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(line.startsWith("Tcp:")) {
|
||||||
|
parseTcp(reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(line.startsWith("Udp:")) {
|
||||||
|
parseUdp(reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
inputStream.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected void parseIp(BufferedReader reader) throws IOException {
|
||||||
|
|
||||||
|
while (reader.ready()) {
|
||||||
|
reader.mark(64);
|
||||||
|
String line = reader.readLine();
|
||||||
|
|
||||||
|
if(!line.startsWith(" ")) {
|
||||||
|
reader.reset();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
line = line.trim();
|
||||||
|
|
||||||
|
if(line.matches("(\\d+) total packets received")) {
|
||||||
|
ipTotalPacketsReceived = getFirstLong(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(line.matches("(\\d+) forwarded")) {
|
||||||
|
ipForwarded = getFirstLong(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(line.matches("(\\d+) incoming packets discarded")) {
|
||||||
|
ipIncomingPacketsDiscarded = getFirstLong(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(line.matches("(\\d+) outgoing packets dropped")) {
|
||||||
|
ipOutgoingPacketsDropped = getFirstLong(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected void parseTcp(BufferedReader reader) throws IOException {
|
||||||
|
|
||||||
|
while (reader.ready()) {
|
||||||
|
reader.mark(64);
|
||||||
|
String line = reader.readLine();
|
||||||
|
|
||||||
|
if(!line.startsWith(" ")) {
|
||||||
|
reader.reset();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
line = line.trim();
|
||||||
|
|
||||||
|
if(line.matches("(\\d+) connections established")) {
|
||||||
|
tcpConnectionsEstablished = getFirstLong(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(line.matches("(\\d+) segments received")) {
|
||||||
|
tcpSegmentsReceived = getFirstLong(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(line.matches("(\\d+) segments sent out")) {
|
||||||
|
tcpSegmentsSent = getFirstLong(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void parseUdp(BufferedReader reader) throws IOException {
|
||||||
|
|
||||||
|
while (reader.ready()) {
|
||||||
|
reader.mark(64);
|
||||||
|
String line = reader.readLine();
|
||||||
|
|
||||||
|
if(!line.startsWith(" ")) {
|
||||||
|
reader.reset();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
line = line.trim();
|
||||||
|
|
||||||
|
if(line.matches("(\\d+) packets received")) {
|
||||||
|
udpPacketsReceived = getFirstLong(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(line.matches("(\\d+) packets sent")) {
|
||||||
|
udpPacketsSent = getFirstLong(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Map<String, String> getTags() {
|
||||||
|
return new HashMap<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, Object> getFields() {
|
||||||
|
Map<String, Object> fields = new HashMap<>();
|
||||||
|
fields.put("ip_forwarded", ipForwarded);
|
||||||
|
fields.put("ip_received", ipTotalPacketsReceived);
|
||||||
|
fields.put("ip_dropped", ipOutgoingPacketsDropped);
|
||||||
|
fields.put("ip_discarded", ipIncomingPacketsDiscarded);
|
||||||
|
|
||||||
|
fields.put("tcp_connections", tcpConnectionsEstablished);
|
||||||
|
fields.put("tcp_pkts_recv", tcpSegmentsReceived);
|
||||||
|
fields.put("tcp_pkts_sent", tcpSegmentsSent);
|
||||||
|
|
||||||
|
fields.put("udp_pkts_recv", udpPacketsReceived);
|
||||||
|
fields.put("udp_pkts_sent", udpPacketsSent);
|
||||||
|
|
||||||
|
return fields;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Long getFirstLong(String line) {
|
||||||
|
return Long.parseLong(line.substring(0, line.indexOf(" ")));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,105 +0,0 @@
|
||||||
package sysmon.plugins.os_linux;
|
|
||||||
|
|
||||||
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 LinuxNetworkDevStat {
|
|
||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(LinuxNetworkDevStat.class);
|
|
||||||
|
|
||||||
private static final Pattern pattern1 = Pattern.compile("^\\s+([a-z]{2,}[0-9]+):.*");
|
|
||||||
private static final Pattern pattern2 = Pattern.compile("^\\s+([a-z]{2,}[0-9]+):\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)");
|
|
||||||
|
|
||||||
private long rxBytes;
|
|
||||||
private long rxPackets;
|
|
||||||
private long rxErrs;
|
|
||||||
|
|
||||||
private long txBytes;
|
|
||||||
private long txPackets;
|
|
||||||
private long txErrs;
|
|
||||||
|
|
||||||
/*
|
|
||||||
Inter-| Receive | Transmit
|
|
||||||
face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed
|
|
||||||
env2: 657010764 483686 0 0 0 0 0 0 55416850 431020 0 0 0 0 0 0
|
|
||||||
env3: 6900272 41836 0 0 0 0 0 0 7667444 41849 0 0 0 0 0 0
|
|
||||||
lo: 3098805 14393 0 0 0 0 0 0 3098805 14393 0 0 0 0 0 0
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
public LinuxNetworkDevStat(List<String> procLines) {
|
|
||||||
|
|
||||||
Matcher matcher1;
|
|
||||||
Matcher matcher2;
|
|
||||||
for(String procLine : procLines) {
|
|
||||||
|
|
||||||
matcher1 = pattern1.matcher(procLine);
|
|
||||||
if(matcher1.matches()) {
|
|
||||||
|
|
||||||
if(matcher1.group(1).equals("lo")) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
matcher2 = pattern2.matcher(procLine);
|
|
||||||
if(matcher2.matches() && matcher2.groupCount() == 17) {
|
|
||||||
|
|
||||||
rxBytes += Long.parseLong(matcher2.group(2));
|
|
||||||
rxPackets += Long.parseLong(matcher2.group(3));
|
|
||||||
rxErrs += Long.parseLong(matcher2.group(4));
|
|
||||||
|
|
||||||
txBytes += Long.parseLong(matcher2.group(10));
|
|
||||||
txPackets += Long.parseLong(matcher2.group(11));
|
|
||||||
txErrs += Long.parseLong(matcher2.group(12));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public long getRxBytes() {
|
|
||||||
return rxBytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getRxPackets() {
|
|
||||||
return rxPackets;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getRxErrs() {
|
|
||||||
return rxErrs;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getTxBytes() {
|
|
||||||
return txBytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getTxPackets() {
|
|
||||||
return txPackets;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getTxErrs() {
|
|
||||||
return txErrs;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public Map<String, String> getTags() {
|
|
||||||
return new HashMap<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<String, Object> getFields() {
|
|
||||||
Map<String, Object> fields = new HashMap<>();
|
|
||||||
fields.put("rxBytes", rxBytes);
|
|
||||||
fields.put("rxPackets", rxPackets);
|
|
||||||
fields.put("txBytes", txBytes);
|
|
||||||
fields.put("txPackets", txPackets);
|
|
||||||
return fields;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,95 +0,0 @@
|
||||||
package sysmon.plugins.os_linux;
|
|
||||||
|
|
||||||
import org.pf4j.Extension;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import sysmon.shared.Measurement;
|
|
||||||
import sysmon.shared.MetricExtension;
|
|
||||||
import sysmon.shared.MetricResult;
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
@Extension
|
|
||||||
public class LinuxProcessorExtension implements MetricExtension {
|
|
||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(LinuxProcessorExtension.class);
|
|
||||||
|
|
||||||
private List<LinuxProcessorProcLine> currentProcessorProc;
|
|
||||||
private List<LinuxProcessorProcLine> previousProcessorProc;
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isSupported() {
|
|
||||||
return System.getProperty("os.name").toLowerCase().contains("linux");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getName() {
|
|
||||||
return "linux-processor";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getProvides() {
|
|
||||||
return "processor";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getDescription() {
|
|
||||||
return "Linux Processor Metrics";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MetricResult getMetrics() {
|
|
||||||
|
|
||||||
LinuxProcessorProcLine proc1 = processFileOutput(readProcFile());
|
|
||||||
|
|
||||||
try {
|
|
||||||
Thread.sleep(1 * 1000); // TODO: Configure sample collect time
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
log.warn("getMetrics() - sleep interrupted");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
LinuxProcessorProcLine proc2 = processFileOutput(readProcFile());
|
|
||||||
|
|
||||||
LinuxProcessorStat stat = new LinuxProcessorStat(proc1, proc2);
|
|
||||||
|
|
||||||
return new MetricResult("processor", new Measurement(stat.getTags(), stat.getFields()));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
protected List<String> readProcFile() {
|
|
||||||
|
|
||||||
List<String> allLines = new ArrayList<>();
|
|
||||||
try {
|
|
||||||
allLines = Files.readAllLines(Paths.get("/proc/stat"), StandardCharsets.UTF_8);
|
|
||||||
} catch (IOException e) {
|
|
||||||
log.error(e.getMessage());
|
|
||||||
}
|
|
||||||
return allLines;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
protected LinuxProcessorProcLine processFileOutput(List<String> inputLines) {
|
|
||||||
|
|
||||||
for(String line : inputLines) {
|
|
||||||
if(line.matches("^cpu\\S+.*")) {
|
|
||||||
return new LinuxProcessorProcLine(line);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -1,95 +0,0 @@
|
||||||
package sysmon.plugins.os_linux;
|
|
||||||
|
|
||||||
public class LinuxProcessorProcLine {
|
|
||||||
|
|
||||||
private final String cpuName;
|
|
||||||
private final long userTime;
|
|
||||||
private final long niceTime;
|
|
||||||
private final long systemTime;
|
|
||||||
private final long idleTime;
|
|
||||||
private final long ioWaitTime;
|
|
||||||
private final long irqTime;
|
|
||||||
private final long softIrqTime;
|
|
||||||
private final long stealTime;
|
|
||||||
private final long guestTime;
|
|
||||||
private final long guestNiceTime;
|
|
||||||
|
|
||||||
|
|
||||||
public LinuxProcessorProcLine(String procString) {
|
|
||||||
|
|
||||||
String[] splitStr = procString.trim().split("\\s+");
|
|
||||||
if(splitStr.length != 11) {
|
|
||||||
throw new UnsupportedOperationException("Linux proc CPU string error: " + procString);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.cpuName = splitStr[0];
|
|
||||||
this.userTime = Long.parseLong(splitStr[1]);
|
|
||||||
this.niceTime = Long.parseLong(splitStr[2]);
|
|
||||||
this.systemTime = Long.parseLong(splitStr[3]);
|
|
||||||
this.idleTime = Long.parseLong(splitStr[4]);
|
|
||||||
this.ioWaitTime = Long.parseLong(splitStr[5]);
|
|
||||||
this.irqTime = Long.parseLong(splitStr[6]);
|
|
||||||
this.softIrqTime = Long.parseLong(splitStr[7]);
|
|
||||||
this.stealTime = Long.parseLong(splitStr[8]);
|
|
||||||
this.guestTime = Long.parseLong(splitStr[9]);
|
|
||||||
this.guestNiceTime = Long.parseLong(splitStr[10]);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getCpuName() {
|
|
||||||
return cpuName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getUserTime() {
|
|
||||||
return userTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getNiceTime() {
|
|
||||||
return niceTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getSystemTime() {
|
|
||||||
return systemTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getIdleTime() {
|
|
||||||
return idleTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getIoWaitTime() {
|
|
||||||
return ioWaitTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getIrqTime() {
|
|
||||||
return irqTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getSoftIrqTime() {
|
|
||||||
return softIrqTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getStealTime() {
|
|
||||||
return stealTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getGuestTime() {
|
|
||||||
return guestTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getGuestNiceTime() {
|
|
||||||
return guestNiceTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getCombinedIdleTime() {
|
|
||||||
return idleTime + ioWaitTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getCombinedWorkTime() {
|
|
||||||
return userTime + niceTime + systemTime + irqTime + softIrqTime + stealTime + guestTime + guestNiceTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getCombinedTime() {
|
|
||||||
return getCombinedIdleTime() + getCombinedWorkTime();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,60 +0,0 @@
|
||||||
package sysmon.plugins.os_linux;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public class LinuxProcessorStat {
|
|
||||||
|
|
||||||
private final float user;
|
|
||||||
private final float sys;
|
|
||||||
private final float wait;
|
|
||||||
private final float idle;
|
|
||||||
private final float busy;
|
|
||||||
|
|
||||||
public LinuxProcessorStat(LinuxProcessorProcLine previous, LinuxProcessorProcLine current) {
|
|
||||||
|
|
||||||
long workTime = current.getCombinedTime() - previous.getCombinedTime();
|
|
||||||
|
|
||||||
long busyTime = current.getCombinedIdleTime() - previous.getCombinedIdleTime();
|
|
||||||
float busyDiff = (float) (workTime - busyTime) / workTime;
|
|
||||||
busy = (busyDiff * 100);
|
|
||||||
|
|
||||||
long userTime = current.getUserTime() - previous.getUserTime();
|
|
||||||
float userDiff = (float) (workTime - userTime) / workTime;
|
|
||||||
user = 100 - (userDiff * 100);
|
|
||||||
|
|
||||||
long sysTime = current.getSystemTime() - previous.getSystemTime();
|
|
||||||
float sysDiff = (float) (workTime - sysTime) / workTime;
|
|
||||||
sys = 100 - (sysDiff * 100);
|
|
||||||
|
|
||||||
long waitTime = current.getIoWaitTime() - previous.getIoWaitTime();
|
|
||||||
float waitDiff = (float) (workTime - waitTime) / workTime;
|
|
||||||
wait = 100 - (waitDiff * 100);
|
|
||||||
|
|
||||||
long idleTime = current.getIdleTime() - previous.getIdleTime();
|
|
||||||
float idleDiff = (float) (workTime - idleTime) / workTime;
|
|
||||||
idle = 100 - (idleDiff * 100);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public Float getBusy() {
|
|
||||||
return busy;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<String, String> getTags() {
|
|
||||||
return new HashMap<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<String, Object> getFields() {
|
|
||||||
Map<String, Object> fields = new HashMap<>();
|
|
||||||
fields.put("user", user);
|
|
||||||
fields.put("sys", sys);
|
|
||||||
fields.put("wait", wait);
|
|
||||||
fields.put("idle", idle);
|
|
||||||
fields.put("busy", busy);
|
|
||||||
return fields;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
|
@ -12,9 +12,9 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@Extension
|
@Extension
|
||||||
public class LinuxNetworkExtension implements MetricExtension {
|
public class LinuxSockstatExtension implements MetricExtension {
|
||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(LinuxNetworkExtension.class);
|
private static final Logger log = LoggerFactory.getLogger(LinuxSockstatExtension.class);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isSupported() {
|
public boolean isSupported() {
|
||||||
|
@ -29,39 +29,34 @@ public class LinuxNetworkExtension implements MetricExtension {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return "linux-network";
|
return "linux-network-sockets";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getProvides() {
|
public String getProvides() {
|
||||||
return "network";
|
return "network-sockets";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getDescription() {
|
public String getDescription() {
|
||||||
return "Linux Network Metrics";
|
return "Linux Network Socket Metrics";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MetricResult getMetrics() {
|
public MetricResult getMetrics() {
|
||||||
|
|
||||||
LinuxNetworkSockStat sockStat = processSockOutput(PluginHelper.readFile("/proc/net/sockstat"));
|
LinuxNetworkSockStat sockStat = processSockOutput(PluginHelper.readFile("/proc/net/sockstat"));
|
||||||
LinuxNetworkDevStat devStat = processDevOutput(PluginHelper.readFile("/proc/net/dev"));
|
|
||||||
|
|
||||||
Map<String, String> tagsMap = sockStat.getTags();
|
Map<String, String> tagsMap = sockStat.getTags();
|
||||||
Map<String, Object> fieldsMap = sockStat.getFields();
|
Map<String, Object> fieldsMap = sockStat.getFields();
|
||||||
fieldsMap.putAll(devStat.getFields());
|
|
||||||
|
|
||||||
return new MetricResult("network", new Measurement(tagsMap, fieldsMap));
|
log.debug(fieldsMap.toString());
|
||||||
|
return new MetricResult("network_sockets", new Measurement(tagsMap, fieldsMap));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected LinuxNetworkSockStat processSockOutput(List<String> inputLines) {
|
protected LinuxNetworkSockStat processSockOutput(List<String> inputLines) {
|
||||||
return new LinuxNetworkSockStat(inputLines);
|
return new LinuxNetworkSockStat(inputLines);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected LinuxNetworkDevStat processDevOutput(List<String> inputLines) {
|
|
||||||
return new LinuxNetworkDevStat(inputLines);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,43 +0,0 @@
|
||||||
import sysmon.plugins.os_linux.LinuxDiskExtension
|
|
||||||
import sysmon.plugins.os_linux.LinuxDiskProcLine
|
|
||||||
import sysmon.plugins.os_linux.LinuxDiskStat
|
|
||||||
import spock.lang.Specification
|
|
||||||
|
|
||||||
class LinuxDiskTest extends Specification {
|
|
||||||
|
|
||||||
void "test proc file processing"() {
|
|
||||||
|
|
||||||
setup:
|
|
||||||
def testFile = new File(getClass().getResource('/proc_diskstats1.txt').toURI())
|
|
||||||
List<String> lines = testFile.readLines("UTF-8")
|
|
||||||
|
|
||||||
when:
|
|
||||||
LinuxDiskExtension extension = new LinuxDiskExtension()
|
|
||||||
LinuxDiskProcLine procLine = extension.processFileOutput(lines)
|
|
||||||
|
|
||||||
then:
|
|
||||||
procLine.getTimeSpentOnIo() == 11145860l
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void "test disk utilization"() {
|
|
||||||
|
|
||||||
setup:
|
|
||||||
def testFile1 = new File(getClass().getResource('/proc_diskstats1.txt').toURI())
|
|
||||||
def testFile2 = new File(getClass().getResource('/proc_diskstats2.txt').toURI())
|
|
||||||
LinuxDiskExtension extension = new LinuxDiskExtension()
|
|
||||||
LinuxDiskProcLine procLine1 = extension.processFileOutput(testFile1.readLines())
|
|
||||||
LinuxDiskProcLine procLine2 = extension.processFileOutput(testFile2.readLines())
|
|
||||||
|
|
||||||
when:
|
|
||||||
LinuxDiskStat diskStat = new LinuxDiskStat(procLine1, procLine2)
|
|
||||||
|
|
||||||
then:
|
|
||||||
diskStat.getFields().get("iotime") == 180L
|
|
||||||
diskStat.getFields().get("writes") == 108371968L
|
|
||||||
diskStat.getFields().get("reads") == 69632L
|
|
||||||
diskStat.getFields().get("kbps") == 105900.0f
|
|
||||||
diskStat.getFields().get("tps") == 97.0f
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,28 +0,0 @@
|
||||||
import sysmon.plugins.os_linux.LinuxMemoryExtension
|
|
||||||
import sysmon.plugins.os_linux.LinuxMemoryStat
|
|
||||||
import spock.lang.Specification
|
|
||||||
|
|
||||||
class LinuxMemoryTest extends Specification {
|
|
||||||
|
|
||||||
void "test Linux free output processing"() {
|
|
||||||
|
|
||||||
setup:
|
|
||||||
def testFile = new File(getClass().getResource('/free.txt').toURI())
|
|
||||||
List<String> lines = testFile.readLines("UTF-8")
|
|
||||||
|
|
||||||
when:
|
|
||||||
LinuxMemoryExtension extension = new LinuxMemoryExtension()
|
|
||||||
LinuxMemoryStat stats = extension.processCommandOutput(lines)
|
|
||||||
|
|
||||||
then:
|
|
||||||
stats.getFields().get("total") == 16069172l
|
|
||||||
stats.getFields().get("used") == 5896832l
|
|
||||||
stats.getFields().get("free") == 4597860l
|
|
||||||
stats.getFields().get("shared") == 639780l
|
|
||||||
stats.getFields().get("buffers") == 5574480l
|
|
||||||
stats.getFields().get("available") == 9192992l
|
|
||||||
stats.getFields().get("usage") == 42.79113f
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
26
plugins/os-linux/src/test/groovy/LinuxNetstatTest.groovy
Normal file
26
plugins/os-linux/src/test/groovy/LinuxNetstatTest.groovy
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
import spock.lang.Specification
|
||||||
|
import sysmon.plugins.os_linux.LinuxNetstatParser
|
||||||
|
|
||||||
|
class LinuxNetstatTest extends Specification {
|
||||||
|
|
||||||
|
void "test netstat parsing"() {
|
||||||
|
|
||||||
|
setup:
|
||||||
|
InputStream inputStream = getClass().getResourceAsStream('/netstat-linux.txt');
|
||||||
|
|
||||||
|
when:
|
||||||
|
LinuxNetstatParser parser = new LinuxNetstatParser(inputStream)
|
||||||
|
|
||||||
|
then:
|
||||||
|
parser.getFields().size() > 0
|
||||||
|
parser.getFields().get('ip_received') == 109772L
|
||||||
|
parser.getFields().get('ip_dropped') == 70L
|
||||||
|
parser.getFields().get('ip_discarded') == 0L
|
||||||
|
parser.getFields().get('tcp_pkts_sent') == 89891L
|
||||||
|
parser.getFields().get('tcp_pkts_recv') == 86167L
|
||||||
|
parser.getFields().get('udp_pkts_sent') == 10682L
|
||||||
|
parser.getFields().get('udp_pkts_recv') == 31928L
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,6 +1,5 @@
|
||||||
import spock.lang.Specification
|
import spock.lang.Specification
|
||||||
import sysmon.plugins.os_linux.LinuxNetworkDevStat
|
import sysmon.plugins.os_linux.LinuxSockstatExtension
|
||||||
import sysmon.plugins.os_linux.LinuxNetworkExtension
|
|
||||||
import sysmon.plugins.os_linux.LinuxNetworkSockStat
|
import sysmon.plugins.os_linux.LinuxNetworkSockStat
|
||||||
|
|
||||||
class LinuxNetworkTest extends Specification {
|
class LinuxNetworkTest extends Specification {
|
||||||
|
@ -12,7 +11,7 @@ class LinuxNetworkTest extends Specification {
|
||||||
List<String> lines = testFile.readLines("UTF-8")
|
List<String> lines = testFile.readLines("UTF-8")
|
||||||
|
|
||||||
when:
|
when:
|
||||||
LinuxNetworkExtension extension = new LinuxNetworkExtension()
|
LinuxSockstatExtension extension = new LinuxSockstatExtension()
|
||||||
LinuxNetworkSockStat stats = extension.processSockOutput(lines)
|
LinuxNetworkSockStat stats = extension.processSockOutput(lines)
|
||||||
|
|
||||||
then:
|
then:
|
||||||
|
@ -27,44 +26,4 @@ class LinuxNetworkTest extends Specification {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void "test /proc/net/dev parsing"() {
|
|
||||||
|
|
||||||
setup:
|
|
||||||
def testFile = new File(getClass().getResource('/proc_net_dev1.txt').toURI())
|
|
||||||
List<String> lines = testFile.readLines("UTF-8")
|
|
||||||
|
|
||||||
when:
|
|
||||||
LinuxNetworkExtension extension = new LinuxNetworkExtension()
|
|
||||||
LinuxNetworkDevStat procLine = extension.processDevOutput(lines)
|
|
||||||
|
|
||||||
then:
|
|
||||||
procLine.getRxBytes() == 663911036L
|
|
||||||
procLine.getRxPackets() == 525522L
|
|
||||||
procLine.getRxErrs() == 0L
|
|
||||||
procLine.getTxBytes() == 63084294L
|
|
||||||
procLine.getTxPackets() == 472869L
|
|
||||||
procLine.getTxErrs() == 0L
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
void "test dev utilization"() {
|
|
||||||
|
|
||||||
setup:
|
|
||||||
def testFile1 = new File(getClass().getResource('/proc_net_dev1.txt').toURI())
|
|
||||||
def testFile2 = new File(getClass().getResource('/proc_net_dev2.txt').toURI())
|
|
||||||
LinuxNetworkExtension extension = new LinuxNetworkExtension()
|
|
||||||
LinuxNetworkDevStat procLine1 = extension.processDevOutput(testFile1.readLines())
|
|
||||||
LinuxNetworkDevStat procLine2 = extension.processDevOutput(testFile2.readLines())
|
|
||||||
|
|
||||||
when:
|
|
||||||
LinuxNetworkDevStat networkDevStat = new LinuxNetworkDevStat(procLine1, procLine2)
|
|
||||||
|
|
||||||
then:
|
|
||||||
networkDevStat.getFields().get("rxPackets") == 223L
|
|
||||||
networkDevStat.getFields().get("rxBytes") == 31501L
|
|
||||||
networkDevStat.getFields().get("txBytes") == 46460L
|
|
||||||
networkDevStat.getFields().get("txPackets") == 341L
|
|
||||||
}*/
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,48 +0,0 @@
|
||||||
import sysmon.plugins.os_linux.LinuxProcessorExtension
|
|
||||||
import sysmon.plugins.os_linux.LinuxProcessorProcLine
|
|
||||||
import sysmon.plugins.os_linux.LinuxProcessorStat
|
|
||||||
import spock.lang.Specification
|
|
||||||
|
|
||||||
class LinuxProcessorTest extends Specification {
|
|
||||||
|
|
||||||
void "test proc file processing"() {
|
|
||||||
|
|
||||||
setup:
|
|
||||||
def testFile = new File(getClass().getResource('/proc_stats1.txt').toURI())
|
|
||||||
List<String> lines = testFile.readLines("UTF-8")
|
|
||||||
|
|
||||||
when:
|
|
||||||
LinuxProcessorExtension extension = new LinuxProcessorExtension()
|
|
||||||
LinuxProcessorProcLine procLine = extension.processFileOutput(lines)
|
|
||||||
|
|
||||||
then:
|
|
||||||
procLine.getSystemTime() == 4686l
|
|
||||||
procLine.getUserTime() == 27477l
|
|
||||||
procLine.getIdleTime() == 281276l
|
|
||||||
procLine.getIoWaitTime() == 252l
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void "test processor utilization"() {
|
|
||||||
|
|
||||||
setup:
|
|
||||||
def testFile1 = new File(getClass().getResource('/proc_stats1.txt').toURI())
|
|
||||||
def testFile2 = new File(getClass().getResource('/proc_stats2.txt').toURI())
|
|
||||||
LinuxProcessorProcLine processorProcLine1 = new LinuxProcessorProcLine(testFile1.readLines().get(0))
|
|
||||||
LinuxProcessorProcLine processorProcLine2 = new LinuxProcessorProcLine(testFile2.readLines().get(0))
|
|
||||||
|
|
||||||
when:
|
|
||||||
LinuxProcessorStat processorStat = new LinuxProcessorStat(processorProcLine1, processorProcLine2)
|
|
||||||
|
|
||||||
then:
|
|
||||||
processorStat.getBusy() == 38.001614f
|
|
||||||
processorStat.getFields().get("user") == 35.6989f
|
|
||||||
processorStat.getFields().get("sys") == 2.2623215f
|
|
||||||
processorStat.getFields().get("idle") == 61.823322f
|
|
||||||
processorStat.getFields().get("wait") == 0.17505646f
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
112
plugins/os-linux/src/test/resources/netstat-linux.txt
Normal file
112
plugins/os-linux/src/test/resources/netstat-linux.txt
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
Ip:
|
||||||
|
Forwarding: 1
|
||||||
|
109772 total packets received
|
||||||
|
1 with invalid addresses
|
||||||
|
0 forwarded
|
||||||
|
0 incoming packets discarded
|
||||||
|
109769 incoming packets delivered
|
||||||
|
103916 requests sent out
|
||||||
|
70 outgoing packets dropped
|
||||||
|
1 dropped because of missing route
|
||||||
|
Icmp:
|
||||||
|
52 ICMP messages received
|
||||||
|
0 input ICMP message failed
|
||||||
|
ICMP input histogram:
|
||||||
|
destination unreachable: 40
|
||||||
|
echo requests: 12
|
||||||
|
108 ICMP messages sent
|
||||||
|
0 ICMP messages failed
|
||||||
|
ICMP output histogram:
|
||||||
|
destination unreachable: 96
|
||||||
|
echo replies: 12
|
||||||
|
IcmpMsg:
|
||||||
|
InType3: 40
|
||||||
|
InType8: 12
|
||||||
|
OutType0: 12
|
||||||
|
OutType3: 96
|
||||||
|
Tcp:
|
||||||
|
3142 active connection openings
|
||||||
|
5 passive connection openings
|
||||||
|
2105 failed connection attempts
|
||||||
|
193 connection resets received
|
||||||
|
70 connections established
|
||||||
|
86167 segments received
|
||||||
|
89891 segments sent out
|
||||||
|
184 segments retransmitted
|
||||||
|
3 bad segments received
|
||||||
|
2735 resets sent
|
||||||
|
Udp:
|
||||||
|
31928 packets received
|
||||||
|
96 packets to unknown port received
|
||||||
|
0 packet receive errors
|
||||||
|
10682 packets sent
|
||||||
|
0 receive buffer errors
|
||||||
|
0 send buffer errors
|
||||||
|
IgnoredMulti: 22
|
||||||
|
UdpLite:
|
||||||
|
TcpExt:
|
||||||
|
30 packets pruned from receive queue because of socket buffer overrun
|
||||||
|
178 TCP sockets finished time wait in fast timer
|
||||||
|
426 delayed acks sent
|
||||||
|
1 delayed acks further delayed because of locked socket
|
||||||
|
Quick ack mode was activated 1059 times
|
||||||
|
45809 packet headers predicted
|
||||||
|
7293 acknowledgments not containing data payload received
|
||||||
|
7659 predicted acknowledgments
|
||||||
|
TCPSackRecovery: 3
|
||||||
|
Detected reordering 4 times using SACK
|
||||||
|
TCPDSACKUndo: 1
|
||||||
|
1 congestion windows recovered without slow start after partial ack
|
||||||
|
TCPLostRetransmit: 82
|
||||||
|
3 timeouts after reno fast retransmit
|
||||||
|
1 timeouts in loss state
|
||||||
|
3 fast retransmits
|
||||||
|
3 retransmits in slow start
|
||||||
|
TCPTimeouts: 129
|
||||||
|
TCPLossProbes: 69
|
||||||
|
TCPLossProbeRecovery: 10
|
||||||
|
TCPBacklogCoalesce: 450
|
||||||
|
TCPDSACKOldSent: 991
|
||||||
|
TCPDSACKOfoSent: 6
|
||||||
|
TCPDSACKRecv: 45
|
||||||
|
202 connections reset due to unexpected data
|
||||||
|
147 connections reset due to early user close
|
||||||
|
13 connections aborted due to timeout
|
||||||
|
TCPDSACKIgnoredNoUndo: 10
|
||||||
|
TCPSackShifted: 1
|
||||||
|
TCPSackMerged: 1
|
||||||
|
TCPSackShiftFallback: 9
|
||||||
|
TCPRcvCoalesce: 5338
|
||||||
|
TCPOFOQueue: 793
|
||||||
|
TCPOFOMerge: 6
|
||||||
|
TCPChallengeACK: 3
|
||||||
|
TCPSYNChallenge: 3
|
||||||
|
TCPSpuriousRtxHostQueues: 6
|
||||||
|
TCPAutoCorking: 710
|
||||||
|
TCPFromZeroWindowAdv: 1
|
||||||
|
TCPToZeroWindowAdv: 1
|
||||||
|
TCPWantZeroWindowAdv: 4
|
||||||
|
TCPSynRetrans: 98
|
||||||
|
TCPOrigDataSent: 19048
|
||||||
|
TCPHystartTrainDetect: 3
|
||||||
|
TCPHystartTrainCwnd: 54
|
||||||
|
TCPHystartDelayDetect: 1
|
||||||
|
TCPHystartDelayCwnd: 24
|
||||||
|
TCPACKSkippedSeq: 1
|
||||||
|
TCPKeepAlive: 2595
|
||||||
|
TCPDelivered: 20025
|
||||||
|
TCPAckCompressed: 260
|
||||||
|
TcpTimeoutRehash: 116
|
||||||
|
IpExt:
|
||||||
|
InMcastPkts: 2257
|
||||||
|
OutMcastPkts: 480
|
||||||
|
InBcastPkts: 98
|
||||||
|
OutBcastPkts: 78
|
||||||
|
InOctets: 147193028
|
||||||
|
OutOctets: 14723163
|
||||||
|
InMcastOctets: 478599
|
||||||
|
OutMcastOctets: 73462
|
||||||
|
InBcastOctets: 10094
|
||||||
|
OutBcastOctets: 5580
|
||||||
|
InNoECTPkts: 177661
|
||||||
|
MPTcpExt:
|
|
@ -36,9 +36,11 @@ public class ServerRouteBuilder extends RouteBuilder {
|
||||||
.to("seda:inbound")
|
.to("seda:inbound")
|
||||||
.endRest();
|
.endRest();
|
||||||
|
|
||||||
|
|
||||||
//from("seda:inbound").log("Got metric from: ${header.component}").to("mock:sink");
|
//from("seda:inbound").log("Got metric from: ${header.component}").to("mock:sink");
|
||||||
|
|
||||||
from("seda:inbound")
|
// TODO: Make 'concurrentConsumers' configurable
|
||||||
|
from("seda:inbound?concurrentConsumers=5")
|
||||||
.log(">>> metric: ${header.hostname} - ${body}")
|
.log(">>> metric: ${header.hostname} - ${body}")
|
||||||
.doTry()
|
.doTry()
|
||||||
.process(new MetricResultToPointProcessor())
|
.process(new MetricResultToPointProcessor())
|
||||||
|
|
|
@ -2,6 +2,8 @@ package sysmon.shared;
|
||||||
|
|
||||||
import org.pf4j.ExtensionPoint;
|
import org.pf4j.ExtensionPoint;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
public interface MetricExtension extends ExtensionPoint {
|
public interface MetricExtension extends ExtensionPoint {
|
||||||
|
|
||||||
boolean isSupported();
|
boolean isSupported();
|
||||||
|
@ -10,5 +12,5 @@ public interface MetricExtension extends ExtensionPoint {
|
||||||
String getProvides();
|
String getProvides();
|
||||||
String getDescription();
|
String getDescription();
|
||||||
|
|
||||||
MetricResult getMetrics();
|
MetricResult getMetrics() throws Exception;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,10 +3,7 @@ package sysmon.shared;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.*;
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
|
@ -23,10 +20,9 @@ public class PluginHelper {
|
||||||
.toLowerCase().startsWith("windows");
|
.toLowerCase().startsWith("windows");
|
||||||
|
|
||||||
|
|
||||||
public static List<String> executeCommand(String... cmd) {
|
public static InputStream executeCommand(String... cmd) {
|
||||||
|
|
||||||
List<String> outputLines = new ArrayList<>();
|
|
||||||
|
|
||||||
|
InputStream inputStream = null;
|
||||||
ProcessBuilder builder = new ProcessBuilder();
|
ProcessBuilder builder = new ProcessBuilder();
|
||||||
if (isWindows) {
|
if (isWindows) {
|
||||||
builder.command("cmd.exe", "/c");
|
builder.command("cmd.exe", "/c");
|
||||||
|
@ -40,15 +36,8 @@ public class PluginHelper {
|
||||||
|
|
||||||
builder.directory(new File(System.getProperty("user.home")));
|
builder.directory(new File(System.getProperty("user.home")));
|
||||||
try {
|
try {
|
||||||
|
|
||||||
Process process = builder.start();
|
Process process = builder.start();
|
||||||
BufferedReader reader =
|
inputStream = process.getInputStream();
|
||||||
new BufferedReader(new InputStreamReader(process.getInputStream()));
|
|
||||||
|
|
||||||
String line;
|
|
||||||
while ((line = reader.readLine()) != null) {
|
|
||||||
outputLines.add(line);
|
|
||||||
}
|
|
||||||
|
|
||||||
int exitCode = process.waitFor();
|
int exitCode = process.waitFor();
|
||||||
if(exitCode > 0) {
|
if(exitCode > 0) {
|
||||||
|
@ -59,7 +48,7 @@ public class PluginHelper {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
return outputLines;
|
return inputStream;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue