From 731d8b8d102e095c078b119c4e9cff51393fa4f6 Mon Sep 17 00:00:00 2001 From: Mark Nellemann Date: Sat, 11 Sep 2021 21:55:48 +0200 Subject: [PATCH] Improvements to network and disk, plus some cleanup and refactoring. --- client/build.gradle | 2 +- client/doc/sysmon-client.toml | 4 +- .../main/java/sysmon/client/Application.java | 9 ++ .../sysmon/client/ClientRouteBuilder.java | 7 +- .../java/sysmon/client/Configuration.java | 8 +- gradle.properties | 2 +- .../plugins/os_aix/AixProcessorExtension.java | 4 +- plugins/os-base/README.md | 18 +++ .../plugins/os_base/BaseDiskExtension.java | 38 ++--- .../os_base/BaseFilesystemExtension.java | 132 ++++++++++++++++++ .../plugins/os_base/BaseNetworkExtension.java | 43 +++--- .../os_linux/LinuxSockstatExtension.java | 2 +- server/build.gradle | 2 +- 13 files changed, 213 insertions(+), 58 deletions(-) create mode 100644 plugins/os-base/src/main/java/sysmon/plugins/os_base/BaseFilesystemExtension.java diff --git a/client/build.gradle b/client/build.gradle index 56ba734..8e7a2ad 100644 --- a/client/build.gradle +++ b/client/build.gradle @@ -37,7 +37,7 @@ def projectName = "sysmon-client" application { // Define the main class for the application. mainClass.set('sysmon.client.Application') - applicationDefaultJvmArgs = [ "-server", "-Xms16m", "-Xmx32m", "-XX:+UseG1GC" ] + applicationDefaultJvmArgs = [ "-server", "-Xmx64m", "-XX:+UseG1GC" ] } run { diff --git a/client/doc/sysmon-client.toml b/client/doc/sysmon-client.toml index 70cf8de..f7bebea 100644 --- a/client/doc/sysmon-client.toml +++ b/client/doc/sysmon-client.toml @@ -1,7 +1,9 @@ # Configuration for sysmon-client +[extension.base_filesystem] + [extension.base_disk] -enabled = false +enabled = true [extension.base_process] enabled = true diff --git a/client/src/main/java/sysmon/client/Application.java b/client/src/main/java/sysmon/client/Application.java index 4fcad29..7a73b52 100644 --- a/client/src/main/java/sysmon/client/Application.java +++ b/client/src/main/java/sysmon/client/Application.java @@ -4,6 +4,7 @@ package sysmon.client; import org.apache.camel.main.Main; +import org.slf4j.impl.SimpleLogger; import picocli.CommandLine; import java.io.File; @@ -28,6 +29,10 @@ public class Application implements Callable { @CommandLine.Option(names = { "-c", "--conf" }, description = "Configuration file [default: '/etc/sysmon-client.toml'].", paramLabel = "", defaultValue = "/etc/sysmon-client.toml") private File configurationFile; + @CommandLine.Option(names = { "-d", "--debug" }, description = "Enable debugging (default: ${DEFAULT_VALUE}).") + private boolean enableDebug = false; + + public static void main(String... args) { int exitCode = new CommandLine(new Application()).execute(args); System.exit(exitCode); @@ -39,6 +44,10 @@ public class Application implements Callable { Configuration configuration = new Configuration(); + if(enableDebug) { + System.setProperty(SimpleLogger.DEFAULT_LOG_LEVEL_KEY, "DEBUG"); + } + if(hostname == null || hostname.isEmpty()) { try { hostname = InetAddress.getLocalHost().getHostName(); diff --git a/client/src/main/java/sysmon/client/ClientRouteBuilder.java b/client/src/main/java/sysmon/client/ClientRouteBuilder.java index 7b08153..ea06665 100644 --- a/client/src/main/java/sysmon/client/ClientRouteBuilder.java +++ b/client/src/main/java/sysmon/client/ClientRouteBuilder.java @@ -55,13 +55,10 @@ public class ClientRouteBuilder extends RouteBuilder { log.info(">>> Enabling extension: " + ext.getDescription()); providers.add(provides); - - // TODO: Make timer thread configurable ? - // 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. - //from("timer:"+provides+"?fixedRate=true&period=30s") - from("timer:extensions?fixedRate=true&period=30s") + //from("timer:extensions?fixedRate=true&period=30s") + from("timer:"+provides+"?fixedRate=true&period=30s") .bean(ext, "getMetrics") //.doTry() .outputType(MetricResult.class) diff --git a/client/src/main/java/sysmon/client/Configuration.java b/client/src/main/java/sysmon/client/Configuration.java index f9a4dfe..90f2227 100644 --- a/client/src/main/java/sysmon/client/Configuration.java +++ b/client/src/main/java/sysmon/client/Configuration.java @@ -46,10 +46,12 @@ public final class Configuration { String key = String.format("extension.%s", extName); TomlTable table = result.getTableOrEmpty(key); table.keySet().forEach( k -> { - if(table.isString(k)) { - map.put(k, table.getString(k)); - } else if(table.isBoolean(k)) { + if(table.isBoolean(k)) { map.put(k, table.getBoolean(k)); + } else if(table.isString(k)) { + map.put(k, table.getString(k)); + } else if(table.isLong(k)) { + map.put(k, table.getLong(k)); } else if(table.isDouble(k)) { map.put(k, table.getDouble(k)); } else if(table.isArray(k)) { diff --git a/gradle.properties b/gradle.properties index 91b92b6..d0d47a7 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ -version=0.0.10 +version=0.0.11 pf4jVersion=3.6.0 slf4jVersion=1.7.32 camelVersion=3.11.1 diff --git a/plugins/os-aix/src/main/java/sysmon/plugins/os_aix/AixProcessorExtension.java b/plugins/os-aix/src/main/java/sysmon/plugins/os_aix/AixProcessorExtension.java index 91855d4..a594174 100644 --- a/plugins/os-aix/src/main/java/sysmon/plugins/os_aix/AixProcessorExtension.java +++ b/plugins/os-aix/src/main/java/sysmon/plugins/os_aix/AixProcessorExtension.java @@ -37,7 +37,7 @@ public class AixProcessorExtension implements MetricExtension { String osArch = System.getProperty("os.arch").toLowerCase(); if(!osArch.startsWith("ppc64")) { - log.warn("Requires CPU Architecture ppc64 or ppc64le, this is: " + osArch); + log.debug("Requires CPU Architecture ppc64 or ppc64le, this is: " + osArch); return false; } @@ -81,6 +81,8 @@ public class AixProcessorExtension implements MetricExtension { AixProcessorStat processorStat = processCommandOutput(buf); tagsMap = processorStat.getTags(); fieldsMap = processorStat.getFields(); + } catch (IOException e) { + log.error("lparstat error", e); } return new MetricResult(name, new Measurement(tagsMap, fieldsMap)); diff --git a/plugins/os-base/README.md b/plugins/os-base/README.md index 3a7e139..e0790fe 100644 --- a/plugins/os-base/README.md +++ b/plugins/os-base/README.md @@ -37,6 +37,24 @@ Metrics reported are: - **iotime** - Time spent on IO in milliseconds. - **queue** - Lenght of IO queue. +## Filesystem Extension + +### Metrics +- +- **free_bytes** - Free bytes for filesystem. +- **total_bytes** - Total bytes for filesystem. +- **free_inoed** - Free inodes for filesystem. +- **total_inodes** - Total inodes for filesystem. + +### Configuration + +```toml +[extension.base_filesystem] +enabled = true +exclude_type = [ "tmpfs", "ahafs" ] +exclude_mount = [ "/boot/efi" ] +``` + ## Process Extension Reports metrics on one or more running processes. diff --git a/plugins/os-base/src/main/java/sysmon/plugins/os_base/BaseDiskExtension.java b/plugins/os-base/src/main/java/sysmon/plugins/os_base/BaseDiskExtension.java index 1fde4b9..01ff3f4 100644 --- a/plugins/os-base/src/main/java/sysmon/plugins/os_base/BaseDiskExtension.java +++ b/plugins/os-base/src/main/java/sysmon/plugins/os_base/BaseDiskExtension.java @@ -9,6 +9,7 @@ import sysmon.shared.Measurement; import sysmon.shared.MetricExtension; import sysmon.shared.MetricResult; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -65,33 +66,32 @@ public class BaseDiskExtension implements MetricExtension { @Override public MetricResult getMetrics() { - long writeBytes = 0L; - long readBytes = 0L; - long transferTime = 0L; - long queueLength = 0L; - - HashMap tagsMap = new HashMap<>(); - HashMap fieldsMap = new HashMap<>(); - + ArrayList measurementList = new ArrayList<>(); List diskStores = hardwareAbstractionLayer.getDiskStores(); + for(HWDiskStore store : diskStores) { + String name = store.getName(); if (name.matches("hdisk[0-9]+") || name.matches("/dev/x?[sv]d[a-z]") || 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(); + + HashMap tagsMap = new HashMap() {{ + put("name", name); + }}; + + HashMap fieldsMap = new HashMap() {{ + put("read", store.getReadBytes()); + put("write", store.getWriteBytes()); + put("iotime", store.getTransferTime()); + put("queue", store.getCurrentQueueLength()); + }}; + + measurementList.add(new Measurement(tagsMap, fieldsMap)); } + } - fieldsMap.put("reads", readBytes); - fieldsMap.put("writes", writeBytes); - fieldsMap.put("iotime", transferTime); - fieldsMap.put("queue", queueLength); + return new MetricResult(name, measurementList); - log.debug(fieldsMap.toString()); - return new MetricResult(name, new Measurement(tagsMap, fieldsMap)); } } \ No newline at end of file diff --git a/plugins/os-base/src/main/java/sysmon/plugins/os_base/BaseFilesystemExtension.java b/plugins/os-base/src/main/java/sysmon/plugins/os_base/BaseFilesystemExtension.java new file mode 100644 index 0000000..384cf7a --- /dev/null +++ b/plugins/os-base/src/main/java/sysmon/plugins/os_base/BaseFilesystemExtension.java @@ -0,0 +1,132 @@ +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.software.os.OSFileStore; +import sysmon.shared.Measurement; +import sysmon.shared.MetricExtension; +import sysmon.shared.MetricResult; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Extension +public class BaseFilesystemExtension implements MetricExtension { + + private static final Logger log = LoggerFactory.getLogger(BaseDiskExtension.class); + + // Extension details + private final String name = "base_filesystem"; + private final String provides = "filesystem"; + private final String description = "Base Filesystem Metrics"; + + // Configuration / Options + private boolean enabled = true; + private List excludeType = new ArrayList() {{ + add("tmpfs"); + add("ahafs"); + }}; + private List excludeMount = new ArrayList() {{ + add("/boot/efi"); + }}; + + private HardwareAbstractionLayer hardwareAbstractionLayer; + private SystemInfo systemInfo; + + + @Override + public boolean isEnabled() { + return enabled; + } + + @Override + public boolean isSupported() { + systemInfo = BasePlugin.getSystemInfo(); + //hardwareAbstractionLayer = BasePlugin.getHardwareAbstractionLayer(); + return systemInfo != null; + } + + @Override + public String getName() { + return name; + } + + @Override + public String getProvides() { + return provides; + } + + @Override + public String getDescription() { + return description; + } + + @Override + public void setConfiguration(Map map) { + if (map.containsKey("enabled")) { + enabled = (boolean) map.get("enabled"); + } + + if(map.containsKey("exclude_type")) { + excludeType = (List) map.get("exclude_type"); + } + + if(map.containsKey("exclude_mount")) { + excludeMount = (List) map.get("exclude_mount"); + } + } + + @Override + public MetricResult getMetrics() { + + ArrayList alreadyProcessed = new ArrayList<>(); + ArrayList measurementList = new ArrayList<>(); + List fileStores = systemInfo.getOperatingSystem().getFileSystem().getFileStores(true); + + for(OSFileStore store : fileStores) { + + String name = store.getName(); + String type = store.getType(); + String mount = store.getMount(); + + if(excludeType.contains(type)) { + log.debug("Excluding type: " + type); + continue; + } + + if(excludeMount.contains(mount)) { + log.debug("Excluding mount: " + mount); + continue; + } + + if(alreadyProcessed.contains(name)) { + log.debug("Skipping name: " + name); + continue; + } + alreadyProcessed.add(name); + + HashMap tagsMap = new HashMap() {{ + put("name", name); + put("type", type); + put("mount", mount); + }}; + + HashMap fieldsMap = new HashMap() {{ + put("free_bytes", store.getFreeSpace()); + put("total_bytes", store.getTotalSpace()); + put("free_inodes", store.getFreeInodes()); + put("total_inodes", store.getTotalInodes()); + }}; + + measurementList.add(new Measurement(tagsMap, fieldsMap)); + } + + return new MetricResult(name, measurementList); + } + +} \ No newline at end of file diff --git a/plugins/os-base/src/main/java/sysmon/plugins/os_base/BaseNetworkExtension.java b/plugins/os-base/src/main/java/sysmon/plugins/os_base/BaseNetworkExtension.java index a8780b6..3380851 100644 --- a/plugins/os-base/src/main/java/sysmon/plugins/os_base/BaseNetworkExtension.java +++ b/plugins/os-base/src/main/java/sysmon/plugins/os_base/BaseNetworkExtension.java @@ -9,6 +9,7 @@ import sysmon.shared.Measurement; import sysmon.shared.MetricExtension; import sysmon.shared.MetricResult; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -65,37 +66,29 @@ public class BaseNetworkExtension implements MetricExtension { @Override public MetricResult getMetrics() { - long rxBytes = 0L; - long rxPackets = 0L; - long rxErrs = 0L; - long txBytes = 0L; - long txPackets = 0L; - long txErrs = 0L; - - HashMap tagsMap = new HashMap<>(); - HashMap fieldsMap = new HashMap<>(); + ArrayList measurementList = new ArrayList<>(); List 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(); + + HashMap tagsMap = new HashMap() {{ + put("name", netif.getName()); + }}; + + HashMap fieldsMap = new HashMap() {{ + put("rx_pkts", netif.getPacketsRecv()); + put("tx_pkts", netif.getPacketsSent()); + put("rx_bytes", netif.getBytesRecv()); + put("tx_bytes", netif.getBytesSent()); + put("rx_errs", netif.getInErrors()); + put("tx_errs", netif.getOutErrors()); + }}; + + measurementList.add(new Measurement(tagsMap, fieldsMap)); } - 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(name, new Measurement(tagsMap, fieldsMap)); + return new MetricResult(name, measurementList); } } diff --git a/plugins/os-linux/src/main/java/sysmon/plugins/os_linux/LinuxSockstatExtension.java b/plugins/os-linux/src/main/java/sysmon/plugins/os_linux/LinuxSockstatExtension.java index adfc8dc..311a625 100644 --- a/plugins/os-linux/src/main/java/sysmon/plugins/os_linux/LinuxSockstatExtension.java +++ b/plugins/os-linux/src/main/java/sysmon/plugins/os_linux/LinuxSockstatExtension.java @@ -35,7 +35,7 @@ public class LinuxSockstatExtension implements MetricExtension { public boolean isSupported() { if(!System.getProperty("os.name").toLowerCase().contains("linux")) { - log.warn("Requires Linux."); + log.debug("Requires Linux."); return false; } diff --git a/server/build.gradle b/server/build.gradle index 3816f9e..fd13fff 100644 --- a/server/build.gradle +++ b/server/build.gradle @@ -28,7 +28,7 @@ def projectName = "sysmon-server" application { // Define the main class for the application. mainClass.set('sysmon.server.Application') - applicationDefaultJvmArgs = [ "-server", "-Xms64m", "-Xmx128m", "-XX:+UseG1GC" ] + applicationDefaultJvmArgs = [ "-server", "-Xmx128m", "-XX:+UseG1GC" ] } tasks.named('test') {