Merged in scripts (pull request #19)

Scripts
This commit is contained in:
Mark Nellemann 2023-01-04 13:45:49 +00:00
commit f9192bd223
76 changed files with 407 additions and 1110 deletions

26
.drone.yml Normal file
View file

@ -0,0 +1,26 @@
---
kind: pipeline
name: default
type: docker
steps:
- name: test
image: eclipse-temurin:8-jdk
commands:
- ./gradlew test
- name: build
image: eclipse-temurin:8-jdk
environment:
AUTH_TOKEN: # Gitea access token ENV variable
from_secret: auth # Name of DroneCI secret exposed above
commands:
- ./gradlew build packages shared:publishLibraryPublicationToGiteaRepository
- for file in server/build/distributions/*.deb ; do curl --user "$${AUTH_TOKEN}" --upload-file "$${file}" "https://git.data.coop/api/packages/${DRONE_REPO_OWNER}/generic/${DRONE_REPO_NAME}/${DRONE_TAG}/$(basename $file)" ; done
- for file in server/build/distributions/*.rpm ; do curl --user "$${AUTH_TOKEN}" --upload-file "$${file}" "https://git.data.coop/api/packages/${DRONE_REPO_OWNER}/generic/${DRONE_REPO_NAME}/${DRONE_TAG}/$(basename $file)" ; done
- for file in client/build/distributions/*.deb ; do curl --user "$${AUTH_TOKEN}" --upload-file "$${file}" "https://git.data.coop/api/packages/${DRONE_REPO_OWNER}/generic/${DRONE_REPO_NAME}/${DRONE_TAG}/$(basename $file)" ; done
- for file in client/build/distributions/*.rpm ; do curl --user "$${AUTH_TOKEN}" --upload-file "$${file}" "https://git.data.coop/api/packages/${DRONE_REPO_OWNER}/generic/${DRONE_REPO_NAME}/${DRONE_TAG}/$(basename $file)" ; done
- for file in plugins/build/distributions/*.deb ; do curl --user "$${AUTH_TOKEN}" --upload-file "$${file}" "https://git.data.coop/api/packages/${DRONE_REPO_OWNER}/generic/${DRONE_REPO_NAME}/${DRONE_TAG}/$(basename $file)" ; done
- for file in plugins/build/distributions/*.rpm ; do curl --user "$${AUTH_TOKEN}" --upload-file "$${file}" "https://git.data.coop/api/packages/${DRONE_REPO_OWNER}/generic/${DRONE_REPO_NAME}/${DRONE_TAG}/$(basename $file)" ; done
when:
event:
- tag

View file

@ -5,4 +5,7 @@ end_of_line = lf
insert_final_newline = true insert_final_newline = true
trim_trailing_whitespace = true trim_trailing_whitespace = true
indent_style = space indent_style = space
indent_size = 4 indent_size = 4
[*.yml]
indent_size = 2

View file

@ -2,6 +2,10 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
## [1.1.1] - 2023-01-xx
- Simplify plugin naming
- Initial support for calling (groovy) scripts
## [1.1.0] - 2022-12-17 ## [1.1.0] - 2022-12-17
- Lower influx time precision from milliseconds to seconds - Lower influx time precision from milliseconds to seconds
- requires you to update server and clients to this version. - requires you to update server and clients to this version.

View file

@ -27,11 +27,14 @@ subprojects {
mavenCentral() mavenCentral()
} }
sourceCompatibility = 1.8 java {
targetCompatibility = 1.8 sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
} }
tasks.create("packages") { tasks.register("packages") {
group "build" group "build"
dependsOn ":client:buildDeb" dependsOn ":client:buildDeb"

View file

@ -3,9 +3,9 @@ import org.redline_rpm.header.Os
plugins { plugins {
id 'application' id 'application'
id "com.github.johnrengelman.shadow" version "7.1.2"
id "net.nemerosa.versioning" version "2.15.1" id "net.nemerosa.versioning" version "2.15.1"
id "nebula.ospackage" version "9.1.1" id "com.github.johnrengelman.shadow" version "7.1.2"
id "com.netflix.nebula.ospackage" version "10.0.0"
} }
dependencies { dependencies {
@ -23,6 +23,9 @@ dependencies {
exclude(group: "org.slf4j") exclude(group: "org.slf4j")
} }
//implementation "org.apache.groovy:groovy-all:${groovyVersion}" // From version 4.+
implementation "org.codehaus.groovy:groovy:${groovyVersion}"
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
@ -73,7 +76,6 @@ shadowJar {
mergeServiceFiles() // Tell plugin to merge duplicate service files mergeServiceFiles() // Tell plugin to merge duplicate service files
} }
apply plugin: 'nebula.ospackage'
ospackage { ospackage {
packageName = projectName packageName = projectName
release = '1' release = '1'

View file

@ -0,0 +1,19 @@
class ExampleScript implements MetricScript {
MetricResult getMetrics() {
Map<String,String> tags = new TreeMap<>();
Map<String,Object> fields = new TreeMap<>();
tags.put("type", "temp");
fields.put("sensor1", 23.2);
fields.put("sensor2", 25.8);
Measurement measurement = new Measurement(tags, fields);
return new MetricResult("script_sensors", measurement);
}
}

View file

@ -0,0 +1,3 @@
# Example Scripts
TODO.

View file

@ -4,6 +4,9 @@
### Example configuration with some default values. ### Example configuration with some default values.
### ###
# Local path for Groovy scripts
scripts = "/opt/sysmon/scripts"
[extension.base_info] [extension.base_info]
enabled = true enabled = true
interval = '60m' interval = '60m'

View file

@ -14,15 +14,25 @@ import sysmon.shared.ComboResult;
import sysmon.shared.MetricExtension; import sysmon.shared.MetricExtension;
import sysmon.shared.MetricResult; import sysmon.shared.MetricResult;
import javax.script.*;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class ClientRouteBuilder extends RouteBuilder { public class ClientRouteBuilder extends RouteBuilder {
private static final Logger log = LoggerFactory.getLogger(ClientRouteBuilder.class); private static final Logger log = LoggerFactory.getLogger(ClientRouteBuilder.class);
private final Set<String> scriptFiles = new HashSet<>();
@Override @Override
public void configure() { public void configure() {
@ -34,12 +44,9 @@ public class ClientRouteBuilder extends RouteBuilder {
pluginManager.loadPlugins(); pluginManager.loadPlugins();
pluginManager.startPlugins(); pluginManager.startPlugins();
List<String> providers = new ArrayList<>();
List<MetricExtension> metricExtensions = pluginManager.getExtensions(MetricExtension.class); List<MetricExtension> metricExtensions = pluginManager.getExtensions(MetricExtension.class);
for (MetricExtension ext : metricExtensions) { for (MetricExtension ext : metricExtensions) {
final String name = ext.getName(); final String name = ext.getName();
final String provides = ext.getProvides();
// Load configuration if available // Load configuration if available
if(configuration.isForExtension(name)) { if(configuration.isForExtension(name)) {
@ -48,33 +55,10 @@ public class ClientRouteBuilder extends RouteBuilder {
} }
if(ext.isSupported() && ext.isEnabled()) { if(ext.isSupported() && ext.isEnabled()) {
addExtensionRoute(ext);
if(providers.contains(provides)) {
log.warn("Skipping extension (already provided): " + ext.getName());
continue;
}
log.info("Enabling extension: " + ext.getDescription());
providers.add(provides);
// 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.
String timerName = ext.isThreaded() ? ext.getProvides() : "default";
String timerInterval = (ext.getInterval() != null) ? ext.getInterval() : "30s";
from("timer:"+timerName+"?fixedRate=true&period="+timerInterval)
.bean(ext, "getMetrics")
.outputType(MetricResult.class)
.process(new MetricEnrichProcessor(registry))
.choice().when(exchangeProperty("skip").isEqualTo(true))
.log(LoggingLevel.WARN,"Skipping empty measurement.")
.stop()
.otherwise()
.log("${body}")
.to("seda:metrics?discardWhenFull=true");
} else { } else {
log.info("Skipping extension (not supported or disabled): " + ext.getDescription()); log.info("Skipping extension (not supported or disabled): " + ext.getDescription());
} }
} }
from("seda:metrics?purgeWhenStopping=true") from("seda:metrics?purgeWhenStopping=true")
@ -97,7 +81,97 @@ public class ClientRouteBuilder extends RouteBuilder {
.log(LoggingLevel.WARN,"Error: ${exception.message}.") .log(LoggingLevel.WARN,"Error: ${exception.message}.")
.end(); .end();
// Find all local scripts
String scriptsPath = configuration.getScriptPath();
if(scriptsPath != null && Files.isDirectory(Paths.get(scriptsPath))) {
try {
scriptFiles.addAll(listFilesByExtension(scriptsPath, "groovy"));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
// Enable the local scripts
for (String scriptFile : scriptFiles) {
try {
ScriptWrapper scriptWrapper = new ScriptWrapper(scriptsPath, scriptFile);
addScriptRoute(scriptWrapper);
} catch(Exception e) {
log.error("configure() - script error: {}", e.getMessage());
}
}
} }
void addScriptRoute(ScriptWrapper script) {
Registry registry = getContext().getRegistry();
from("timer:scripts?fixedRate=true&period=30s")
.bean(script, "run")
.outputType(MetricResult.class)
.process(new MetricEnrichProcessor(registry))
.choice().when(exchangeProperty("skip").isEqualTo(true))
.log(LoggingLevel.WARN, "Skipping empty measurement.")
.stop()
.otherwise()
.log("${body}")
.to("seda:metrics?discardWhenFull=true");
}
void addExtensionRoute(MetricExtension ext) {
Registry registry = getContext().getRegistry();
// 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.
String timerName = ext.isThreaded() ? ext.getName() : "default";
String timerInterval = (ext.getInterval() != null) ? ext.getInterval() : "30s";
from("timer:" + timerName + "?fixedRate=true&period=" + timerInterval)
.bean(ext, "getMetrics")
.outputType(MetricResult.class)
.process(new MetricEnrichProcessor(registry))
.choice().when(exchangeProperty("skip").isEqualTo(true))
.log(LoggingLevel.WARN, "Skipping empty measurement.")
.stop()
.otherwise()
.log("${body}")
.to("seda:metrics?discardWhenFull=true");
}
List<String> findScripts(String location) {
log.info("Looking for scripts in: {}", location);
List<String> scripts = new ArrayList<>();
ScriptEngineManager manager = new ScriptEngineManager();
List<ScriptEngineFactory> factoryList = manager.getEngineFactories();
for (ScriptEngineFactory factory : factoryList) {
log.info("findScripts() - Supporting: {}", factory.getLanguageName());
for(String ex : factory.getExtensions()) {
log.info("findScripts() - Extension: {}", ex);
try {
scripts.addAll(listFilesByExtension(location, ex));
log.warn(scripts.toString());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
return scripts;
}
Set<String> listFilesByExtension(String dir, String ext) throws IOException {
try (Stream<Path> stream = Files.list(Paths.get(dir))) {
return stream
.filter(file -> !Files.isDirectory(file))
.map(Path::getFileName)
.map(Path::toString)
.filter(s -> s.endsWith(ext))
.collect(Collectors.toSet());
}
}
} }

View file

@ -65,4 +65,10 @@ public final class Configuration {
return map; return map;
} }
String getScriptPath() {
return result.getString("scripts");
}
} }

View file

@ -0,0 +1,40 @@
package sysmon.client;
import groovy.lang.GroovyClassLoader;
import groovy.lang.GroovyObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sysmon.shared.MetricResult;
import sysmon.shared.MetricScript;
import java.io.File;
import java.io.IOException;
public class ScriptWrapper {
private static final Logger log = LoggerFactory.getLogger(ScriptWrapper.class);
private final static GroovyClassLoader loader = new GroovyClassLoader();
private GroovyObject script;
public ScriptWrapper(String scriptPath, String scriptFile) {
try {
Class scriptClass = loader.parseClass(new File(scriptPath, scriptFile));
script = (GroovyObject) scriptClass.newInstance();
} catch (IOException |InstantiationException | IllegalAccessException e) {
log.error("ScriptWrapper() - error: {}", e.getMessage());
}
}
MetricResult run() {
MetricResult result = null;
if (script != null && script instanceof MetricScript) {
result = (MetricResult) script.invokeMethod("getMetrics", null);
}
return result;
}
}

View file

@ -1,8 +1,8 @@
version = 1.1.0 version = 1.1.0
pf4jVersion = 3.7.0 pf4jVersion = 3.7.0
slf4jVersion = 2.0.5 slf4jVersion = 2.0.6
camelVersion = 3.14.5 camelVersion = 3.14.7
groovyVersion = 3.0.13 groovyVersion = 3.0.14
picocliVersion = 4.7.0 picocliVersion = 4.7.0
oshiVersion = 6.4.0 oshiVersion = 6.4.0
spockVersion = 2.3-groovy-3.0 spockVersion = 2.3-groovy-3.0

Binary file not shown.

View file

@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists

6
gradlew vendored
View file

@ -205,6 +205,12 @@ set -- \
org.gradle.wrapper.GradleWrapperMain \ org.gradle.wrapper.GradleWrapperMain \
"$@" "$@"
# Stop when "xargs" is not available.
if ! command -v xargs >/dev/null 2>&1
then
die "xargs is not available"
fi
# Use "xargs" to parse quoted args. # Use "xargs" to parse quoted args.
# #
# With -n1 it outputs one arg per line, with the quotes and backslashes removed. # With -n1 it outputs one arg per line, with the quotes and backslashes removed.

14
gradlew.bat vendored
View file

@ -14,7 +14,7 @@
@rem limitations under the License. @rem limitations under the License.
@rem @rem
@if "%DEBUG%" == "" @echo off @if "%DEBUG%"=="" @echo off
@rem ########################################################################## @rem ##########################################################################
@rem @rem
@rem Gradle startup script for Windows @rem Gradle startup script for Windows
@ -25,7 +25,7 @@
if "%OS%"=="Windows_NT" setlocal if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0 set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=. if "%DIRNAME%"=="" set DIRNAME=.
set APP_BASE_NAME=%~n0 set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME% set APP_HOME=%DIRNAME%
@ -40,7 +40,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1 %JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto execute if %ERRORLEVEL% equ 0 goto execute
echo. echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
@ -75,13 +75,15 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
:end :end
@rem End local scope for the variables with windows NT shell @rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd if %ERRORLEVEL% equ 0 goto mainEnd
:fail :fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code! rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 set EXIT_CODE=%ERRORLEVEL%
exit /b 1 if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%
:mainEnd :mainEnd
if "%OS%"=="Windows_NT" endlocal if "%OS%"=="Windows_NT" endlocal

View file

@ -2,6 +2,5 @@
Collection of standard sysmon plugins for use with the client. Collection of standard sysmon plugins for use with the client.
- [base](os-base/README.md) - Base OS metrics (uses [oshi](https://github.com/oshi/oshi)) - [base](base/README.md) - Base OS metrics (uses [oshi](https://github.com/oshi/oshi))
- [aix](os-aix/README.md) - AIX (and IBM Power) specific metrics - [power](power/README.md) - IBM Power specific metrics
- [linux](os-linux/README.md) - Linux specific metrics

View file

@ -1,5 +1,5 @@
pluginId=sysmon-base pluginId=sysmon-base
pluginClass=sysmon.plugins.os_base.BasePlugin pluginClass=sysmon.plugins.base.BasePlugin
pluginDependencies= pluginDependencies=
pluginDescription=Base OS metrics where supported. pluginDescription=Base OS metrics where supported.

View file

@ -1,4 +1,4 @@
package sysmon.plugins.os_base; package sysmon.plugins.base;
import org.pf4j.Extension; import org.pf4j.Extension;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -18,7 +18,6 @@ public class BaseDiskExtension implements MetricExtension {
// Extension details // Extension details
private final String name = "base_disk"; private final String name = "base_disk";
private final String provides = "disk";
private final String description = "Base Disk Metrics"; private final String description = "Base Disk Metrics";
// Configuration / Options // Configuration / Options
@ -57,11 +56,6 @@ public class BaseDiskExtension implements MetricExtension {
return interval; return interval;
} }
@Override
public String getProvides() {
return provides;
}
@Override @Override
public String getDescription() { public String getDescription() {
return description; return description;

View file

@ -1,4 +1,4 @@
package sysmon.plugins.os_base; package sysmon.plugins.base;
import org.pf4j.Extension; import org.pf4j.Extension;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -19,7 +19,6 @@ public class BaseFilesystemExtension implements MetricExtension {
// Extension details // Extension details
private final String name = "base_filesystem"; private final String name = "base_filesystem";
private final String provides = "filesystem";
private final String description = "Base Filesystem Metrics"; private final String description = "Base Filesystem Metrics";
// Configuration / Options // Configuration / Options
@ -67,11 +66,6 @@ public class BaseFilesystemExtension implements MetricExtension {
return interval; return interval;
} }
@Override
public String getProvides() {
return provides;
}
@Override @Override
public String getDescription() { public String getDescription() {
return description; return description;

View file

@ -1,4 +1,4 @@
package sysmon.plugins.os_base; package sysmon.plugins.base;
import org.pf4j.Extension; import org.pf4j.Extension;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -19,7 +19,6 @@ public class BaseInfoExtension implements MetricExtension {
// Extension details // Extension details
private final String name = "base_info"; private final String name = "base_info";
private final String provides = "info";
private final String description = "Base System Information"; private final String description = "Base System Information";
// Configuration / Options // Configuration / Options
@ -52,11 +51,6 @@ public class BaseInfoExtension implements MetricExtension {
return name; return name;
} }
@Override
public String getProvides() {
return provides;
}
@Override @Override
public String getInterval() { return interval; } public String getInterval() { return interval; }

View file

@ -1,4 +1,4 @@
package sysmon.plugins.os_base; package sysmon.plugins.base;
import org.pf4j.Extension; import org.pf4j.Extension;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -8,7 +8,6 @@ import sysmon.shared.Measurement;
import sysmon.shared.MetricExtension; import sysmon.shared.MetricExtension;
import sysmon.shared.MetricResult; import sysmon.shared.MetricResult;
import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.TreeMap; import java.util.TreeMap;
@ -19,7 +18,6 @@ public class BaseLoadExtension implements MetricExtension {
// Extension details // Extension details
private final String name = "base_load"; private final String name = "base_load";
private final String provides = "load";
private final String description = "Base Load Average Metrics"; private final String description = "Base Load Average Metrics";
// Configuration / Options // Configuration / Options
@ -55,11 +53,6 @@ public class BaseLoadExtension implements MetricExtension {
return interval; return interval;
} }
@Override
public String getProvides() {
return provides;
}
@Override @Override
public String getDescription() { public String getDescription() {
return description; return description;

View file

@ -1,4 +1,4 @@
package sysmon.plugins.os_base; package sysmon.plugins.base;
import org.pf4j.Extension; import org.pf4j.Extension;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -8,7 +8,6 @@ import sysmon.shared.Measurement;
import sysmon.shared.MetricExtension; import sysmon.shared.MetricExtension;
import sysmon.shared.MetricResult; import sysmon.shared.MetricResult;
import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.TreeMap; import java.util.TreeMap;
@ -19,7 +18,6 @@ public class BaseMemoryExtension implements MetricExtension {
// Extension details // Extension details
private final String name = "base_memory"; private final String name = "base_memory";
private final String provides = "memory";
private final String description = "Base Memory Metrics"; private final String description = "Base Memory Metrics";
// Configuration / Options // Configuration / Options
@ -56,11 +54,6 @@ public class BaseMemoryExtension implements MetricExtension {
return interval; return interval;
} }
@Override
public String getProvides() {
return provides;
}
@Override @Override
public String getDescription() { public String getDescription() {
return description; return description;

View file

@ -1,4 +1,4 @@
package sysmon.plugins.os_base; package sysmon.plugins.base;
import org.pf4j.Extension; import org.pf4j.Extension;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -8,7 +8,6 @@ import sysmon.shared.Measurement;
import sysmon.shared.MetricExtension; import sysmon.shared.MetricExtension;
import sysmon.shared.MetricResult; import sysmon.shared.MetricResult;
import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.TreeMap; import java.util.TreeMap;
@ -19,7 +18,6 @@ public class BaseNetstatExtension implements MetricExtension {
// Extension details // Extension details
private final String name = "base_netstat"; private final String name = "base_netstat";
private final String provides = "netstat";
private final String description = "Base Netstat Metrics"; private final String description = "Base Netstat Metrics";
// Configuration / Options // Configuration / Options
@ -56,11 +54,6 @@ public class BaseNetstatExtension implements MetricExtension {
return interval; return interval;
} }
@Override
public String getProvides() {
return provides;
}
@Override @Override
public String getDescription() { public String getDescription() {
return description; return description;

View file

@ -1,4 +1,4 @@
package sysmon.plugins.os_base; package sysmon.plugins.base;
import org.pf4j.Extension; import org.pf4j.Extension;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -18,7 +18,6 @@ public class BaseNetworkExtension implements MetricExtension {
// Extension details // Extension details
private final String name = "base_network"; private final String name = "base_network";
private final String provides = "network";
private final String description = "Base Network Metrics"; private final String description = "Base Network Metrics";
// Configuration / Options // Configuration / Options
@ -57,11 +56,6 @@ public class BaseNetworkExtension implements MetricExtension {
return interval; return interval;
} }
@Override
public String getProvides() {
return provides;
}
@Override @Override
public String getDescription() { public String getDescription() {
return description; return description;

View file

@ -1,4 +1,4 @@
package sysmon.plugins.os_base; package sysmon.plugins.base;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;

View file

@ -1,4 +1,4 @@
package sysmon.plugins.os_base; package sysmon.plugins.base;
import org.pf4j.Extension; import org.pf4j.Extension;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -18,7 +18,6 @@ public class BaseProcessExtension implements MetricExtension {
// Extension details // Extension details
private final String name = "base_process"; private final String name = "base_process";
private final String provides = "process";
private final String description = "Base Process Metrics"; private final String description = "Base Process Metrics";
// Configuration / Options // Configuration / Options
@ -75,11 +74,6 @@ public class BaseProcessExtension implements MetricExtension {
return interval; return interval;
} }
@Override
public String getProvides() {
return provides;
}
@Override @Override
public String getDescription() { public String getDescription() {
return description; return description;

View file

@ -1,4 +1,4 @@
package sysmon.plugins.os_base; package sysmon.plugins.base;
import org.pf4j.Extension; import org.pf4j.Extension;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -10,7 +10,6 @@ import sysmon.shared.MetricExtension;
import sysmon.shared.MetricResult; import sysmon.shared.MetricResult;
import sysmon.shared.PluginHelper; import sysmon.shared.PluginHelper;
import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.TreeMap; import java.util.TreeMap;
@ -21,7 +20,6 @@ public class BaseProcessorExtension implements MetricExtension {
// Extension details // Extension details
private final String name = "base_processor"; private final String name = "base_processor";
private final String provides = "processor";
private final String description = "Base Processor Metrics"; private final String description = "Base Processor Metrics";
// Configuration / Options // Configuration / Options
@ -58,11 +56,6 @@ public class BaseProcessorExtension implements MetricExtension {
return interval; return interval;
} }
@Override
public String getProvides() {
return provides;
}
@Override @Override
public String getDescription() { public String getDescription() {
return description; return description;

View file

@ -1,7 +1,7 @@
import org.redline_rpm.header.Os import org.redline_rpm.header.Os
plugins { plugins {
id "nebula.ospackage" version "9.1.1" id "com.netflix.nebula.ospackage" version "10.0.0"
} }
@ -82,7 +82,6 @@ tasks.clean.dependsOn(tasks.customCleanUp)
def projectName = "sysmon-plugins" def projectName = "sysmon-plugins"
apply plugin: 'nebula.ospackage'
ospackage { ospackage {
packageName = projectName packageName = projectName
release = '1' release = '1'

View file

@ -0,0 +1,39 @@
{
"k10temp-pci-00c3":{
"Adapter": "PCI adapter",
"Tctl":{
"temp1_input": 56.250
}
},
"nvme-pci-0400":{
"Adapter": "PCI adapter",
"Composite":{
"temp1_input": 35.850,
"temp1_max": 74.850,
"temp1_min": -20.150,
"temp1_crit": 79.850,
"temp1_alarm": 0.000
}
},
"iwlwifi_1-virtual-0":{
"Adapter": "Virtual device",
"temp1":{
"temp1_input": 37.000
}
},
"amdgpu-pci-0500":{
"Adapter": "PCI adapter",
"vddgfx":{
"in0_input": 0.681
},
"vddnb":{
"in1_input": 0.712
},
"edge":{
"temp1_input": 37.000
},
"PPT":{
"power1_average": 0.000
}
}
}

View file

@ -0,0 +1,39 @@
{
"k10temp-pci-00c3":{
"Adapter": "PCI adapter",
"Tctl":{
"temp1_input": 53.875
}
},
"nvme-pci-0400":{
"Adapter": "PCI adapter",
"Composite":{
"temp1_input": 36.850,
"temp1_max": 74.850,
"temp1_min": -20.150,
"temp1_crit": 79.850,
"temp1_alarm": 0.000
}
},
"iwlwifi_1-virtual-0":{
"Adapter": "Virtual device",
"temp1":{
"temp1_input": 41.000
}
},
"amdgpu-pci-0500":{
"Adapter": "PCI adapter",
"vddgfx":{
"in0_input": 1.281
},
"vddnb":{
"in1_input": 0.712
},
"edge":{
"temp1_input": 42.000
},
"PPT":{
"power1_average": 0.000
}
}
}

View file

@ -1,6 +0,0 @@
pluginId=sysmon-aix
pluginClass=sysmon.plugins.os_aix.AixPlugin
pluginVersion=0.0.1
pluginProvider=System Monitor
pluginDependencies=
pluginDescription=Collects AIX OS metrics.

View file

@ -1,18 +0,0 @@
package sysmon.plugins.os_aix;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.pf4j.Plugin;
import org.pf4j.PluginWrapper;
public class AixPlugin extends Plugin {
private static final Logger log = LoggerFactory.getLogger(AixPlugin.class);
public AixPlugin(PluginWrapper wrapper) {
super(wrapper);
}
}

View file

@ -1,4 +0,0 @@
# IBM i Plugin
This is just for testing purposes.

View file

@ -1,7 +0,0 @@
plugins {
}
dependencies {
// https://sourceforge.net/projects/jt400/ and http://jt400.sourceforge.net/
implementation group: 'net.sf.jt400', name: 'jt400', version: '11.0'
}

View file

@ -1,4 +0,0 @@
pluginId=sysmon-ibmi
pluginClass=sysmon.plugins.os_ibmi.IbmIPlugin
pluginDependencies=
pluginDescription=Collects IBM-i OS metrics.

View file

@ -1,97 +0,0 @@
package sysmon.plugins.os_ibmi;
import com.ibm.as400.access.AS400;
import com.ibm.as400.access.SystemStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.pf4j.Plugin;
import org.pf4j.PluginWrapper;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class IbmIPlugin extends Plugin {
private static final Logger log = LoggerFactory.getLogger(IbmIPlugin.class);
private static AS400 as400;
private static SystemStatus systemStatus;
private static Connection connection;
public IbmIPlugin(PluginWrapper wrapper) {
super(wrapper);
}
public static AS400 getAS400() {
if(as400 != null) {
return as400;
}
// Check platform
String osArch = System.getProperty("os.arch").toLowerCase();
String osName = System.getProperty("os.name").toLowerCase();
if(!osArch.equals("ppc64") && !osName.equals("os/400")) {
log.info("getAS400() - OS Arch: {}", osArch);
log.info("getAS400() - OS Name: {}", osName);
return null;
}
try {
as400 = new AS400("localhost", "*CURRENT");
//as400 = new AS400("localhost", "*LOCAL");
//as400 = new AS400("10.32.64.142");
return as400;
} catch (Exception exception) {
log.error("getAS400() - {}", exception.getMessage());
}
return null;
}
public static SystemStatus getSystemStatus() {
if(systemStatus != null) {
return systemStatus;
}
try {
if (as400 == null) {
as400 = IbmIPlugin.getAS400();
}
if(systemStatus == null && as400 != null) {
systemStatus = new SystemStatus(as400);
return systemStatus;
}
} catch (Exception exception) {
log.error("getSystemStatus() - {}", exception.getMessage());
}
return null;
}
public static Connection getConnection() {
if(connection != null) {
return connection;
}
try {
DriverManager.registerDriver(new com.ibm.as400.access.AS400JDBCDriver());
connection = DriverManager.getConnection("jdbc:as400://localhost");
return connection;
} catch (SQLException exception) {
log.error("getConnection() - {}", exception.getMessage());
}
return null;
}
}

View file

@ -1,146 +0,0 @@
package sysmon.plugins.os_ibmi;
import com.ibm.as400.access.*;
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.util.HashMap;
import java.util.Map;
import java.util.TreeMap;
//@Extension
public class TestExtension implements MetricExtension {
private static final Logger log = LoggerFactory.getLogger(TestExtension.class);
// Extension details
private final String name = "ibmi_test";
private final String provides = "ibmi_test";
private final String description = "IBM i Test Metrics";
// Configuration / Options
private boolean enabled = true;
private boolean threaded = false;
private String interval = "10s";
private SystemStatus systemStatus;
@Override
public boolean isEnabled() {
return enabled;
}
@Override
public boolean isThreaded() {
return threaded;
}
@Override
public boolean isSupported() {
systemStatus = IbmIPlugin.getSystemStatus();
return systemStatus != null;
}
@Override
public String getName() {
return name;
}
@Override
public String getInterval() {
return interval;
}
@Override
public String getProvides() {
return provides;
}
@Override
public String getDescription() {
return description;
}
@Override
public void setConfiguration(Map<String, Object> map) {
if (map.containsKey("enabled")) {
enabled = (boolean) map.get("enabled");
}
if(map.containsKey("threaded")) {
threaded = (boolean) map.get("threaded");
}
if(map.containsKey("interval")) {
interval = (String) map.get("interval");
}
}
@Override
public MetricResult getMetrics() {
if(systemStatus == null) {
log.warn("getMetrics() - no system or status");
return null;
}
/* const hSql = "select
SERVER_NAME,
HTTP_FUNCTION,
SERVER_NORMAL_CONNECTIONS,
SERVER_ACTIVE_THREADS,
SERVER_IDLE_THREADS,
BYTES_RECEIVED,
BYTES_SENT,
NONCACHE_PROCESSING_TIME,
CACHE_PROCESSING_TIME
from
QSYS2.HTTP_SERVER_INFO";
*/
try {
int jobsInSystem = systemStatus.getJobsInSystem();
log.info("Jobs In System: {}", jobsInSystem);
int batchJobsRunning = systemStatus.getBatchJobsRunning();
log.info("Batch Jobs Running: {}", batchJobsRunning);
int activeThreads = systemStatus.getActiveThreadsInSystem();
log.info("Active Threads: {}", activeThreads);
int activeJobs = systemStatus.getActiveJobsInSystem();
log.info("Active Jobs: {}", activeJobs);
int onlineUsers = systemStatus.getUsersCurrentSignedOn();
log.info("Online Users: {}", onlineUsers);
// The storage capacity of the system auxiliary storage pool (ASP1) in MBytes.
long systemAsp = systemStatus.getSystemASP();
System.out.println("Current Processing Capacity :" + systemStatus.getCurrentProcessingCapacity());
System.out.println("ASPUsed:" + systemStatus.getPercentSystemASPUsed());
System.out.println("Temp Addresses Used:" + systemStatus.getPercentTemporaryAddresses());
TreeMap<String, Object> fieldsMap = new TreeMap<String, Object>() {{
put("jobs_total", jobsInSystem);
put("jobs_running", batchJobsRunning);
put("jobs_active", activeJobs);
put("threads", activeThreads);
put("users", onlineUsers);
}};
return new MetricResult(name, new Measurement(new TreeMap<>(), fieldsMap));
} catch (AS400SecurityException | ErrorCompletingRequestException | InterruptedException | IOException | ObjectDoesNotExistException e) {
log.error("getMetrics() {}", e.getMessage());
e.printStackTrace();
}
return null;
}
}

View file

@ -1,7 +0,0 @@
# Linux Plugins
## Components
### Network Sockets
Collects statistics from */proc/net/sockstats*.

View file

@ -1,2 +0,0 @@
plugins {
}

View file

@ -1,5 +0,0 @@
pluginId=sysmon-linux
pluginClass=sysmon.plugins.os_linux.LinuxPlugin
pluginDependencies=
pluginDescription=Linux OS Metrics.

View file

@ -1,109 +0,0 @@
package sysmon.plugins.os_linux;
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.HashMap;
import java.util.Map;
import java.util.TreeMap;
// Disabled
//@Extension
public class LinuxNetstatExtension implements MetricExtension {
private static final Logger log = LoggerFactory.getLogger(LinuxNetstatExtension.class);
// Extension details
private final String name = "linux_network_netstat";
private final String provides = "network_netstat";
private final String description = "Linux Netstat Metrics";
// Configuration / Options
private boolean enabled = true;
private boolean threaded = false;
@Override
public boolean isEnabled() {
return enabled;
}
@Override
public boolean isThreaded() {
return threaded;
}
@Override
public boolean isSupported() {
if(!System.getProperty("os.name").toLowerCase().contains("linux")) {
log.warn("Requires Linux.");
return false;
}
if(PluginHelper.notExecutable("netstat")) {
log.warn("Requires the 'netstat' command.");
return false;
}
return true;
}
@Override
public String getName() {
return name;
}
@Override
public String getInterval() {
return null;
}
@Override
public String getProvides() {
return provides;
}
@Override
public String getDescription() {
return description;
}
@Override
public void setConfiguration(Map<String, Object> map) {
if (map.containsKey("enabled")) {
enabled = (boolean) map.get("enabled");
}
if(map.containsKey("threaded")) {
threaded = (boolean) map.get("threaded");
}
}
@Override
public MetricResult getMetrics() throws Exception {
TreeMap<String, String> tagsMap;
TreeMap<String, Object> fieldsMap;
try (InputStream inputStream = PluginHelper.executeCommand("netstat -s")) {
LinuxNetstatParser parser = processCommandOutput(inputStream);
tagsMap = parser.getTags();
fieldsMap = parser.getFields();
}
return new MetricResult(name, new Measurement(tagsMap, fieldsMap));
}
protected LinuxNetstatParser processCommandOutput(InputStream input) throws IOException {
return new LinuxNetstatParser(input);
}
}

View file

@ -1,165 +0,0 @@
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.TreeMap;
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 TreeMap<String, String> getTags() {
return new TreeMap<>();
}
public TreeMap<String, Object> getFields() {
return new TreeMap<String, Object>() {{
put("ip_forwarded", ipForwarded);
put("ip_received", ipTotalPacketsReceived);
put("ip_dropped", ipOutgoingPacketsDropped);
put("ip_discarded", ipIncomingPacketsDiscarded);
put("tcp_connections", tcpConnectionsEstablished);
put("tcp_pkts_recv", tcpSegmentsReceived);
put("tcp_pkts_sent", tcpSegmentsSent);
put("udp_pkts_recv", udpPacketsReceived);
put("udp_pkts_sent", udpPacketsSent);
}};
}
private Long getFirstLong(String line) {
return Long.parseLong(line.substring(0, line.indexOf(" ")));
}
}

View file

@ -1,17 +0,0 @@
package sysmon.plugins.os_linux;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.pf4j.Plugin;
import org.pf4j.PluginWrapper;
public class LinuxPlugin extends Plugin {
private static final Logger log = LoggerFactory.getLogger(LinuxPlugin.class);
public LinuxPlugin(PluginWrapper wrapper) {
super(wrapper);
}
}

View file

@ -1,98 +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.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
@Extension
public class LinuxSocketExtension implements MetricExtension {
private static final Logger log = LoggerFactory.getLogger(LinuxSocketExtension.class);
// Extension details
private final String name = "linux_network_sockets";
private final String provides = "network_sockets";
private final String description = "Linux Network Socket Metrics";
// Configuration / Options
private boolean enabled = true;
private boolean threaded = false;
@Override
public boolean isEnabled() {
return enabled;
}
@Override
public boolean isThreaded() {
return threaded;
}
@Override
public boolean isSupported() {
if(!System.getProperty("os.name").toLowerCase().contains("linux")) {
log.debug("Requires Linux.");
return false;
}
return true;
}
@Override
public String getName() {
return name;
}
@Override
public String getInterval() {
return null;
}
@Override
public String getProvides() {
return provides;
}
@Override
public String getDescription() {
return description;
}
@Override
public void setConfiguration(Map<String, Object> map) {
if (map.containsKey("enabled")) {
enabled = (boolean) map.get("enabled");
}
if(map.containsKey("threaded")) {
threaded = (boolean) map.get("threaded");
}
}
@Override
public MetricResult getMetrics() {
LinuxSocketStat sockStat = processSockOutput(PluginHelper.readFile("/proc/net/sockstat"));
TreeMap<String, String> tagsMap = sockStat.getTags();
TreeMap<String, Object> fieldsMap = sockStat.getFields();
log.debug("getMetrics() - tags: {}, fields: {}", tagsMap, fieldsMap);
return new MetricResult(name, new Measurement(tagsMap, fieldsMap));
}
protected LinuxSocketStat processSockOutput(List<String> inputLines) {
return new LinuxSocketStat(inputLines);
}
}

View file

@ -1,97 +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.TreeMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class LinuxSocketStat {
private static final Logger log = LoggerFactory.getLogger(LinuxSocketStat.class);
private static final Pattern pattern1 = Pattern.compile("^sockets: used (\\d+)");
private static final Pattern pattern2 = Pattern.compile("^TCP: inuse (\\d+) orphan (\\d+) tw (\\d+) alloc (\\d+) mem (\\d+)");
private static final Pattern pattern3 = Pattern.compile("^UDP: inuse (\\d+) mem (\\d+)");
private long sockets;
private long tcp_inuse;
private long tcp_orphan;
private long tcp_tw;
private long tcp_alloc;
private long tcp_mem;
private long udp_inuse;
private long udp_mem;
/*
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
*/
LinuxSocketStat(List<String> lines) {
Matcher matcher;
for(String line : lines) {
String proto = line.substring(0, line.indexOf(':'));
switch (proto) {
case "sockets":
matcher = pattern1.matcher(line);
if (matcher.matches() && matcher.groupCount() == 1) {
sockets = Long.parseLong(matcher.group(1));
}
break;
case "TCP":
matcher = pattern2.matcher(line);
if (matcher.matches() && matcher.groupCount() == 5) {
tcp_inuse = Long.parseLong(matcher.group(1));
tcp_orphan = Long.parseLong(matcher.group(2));
tcp_tw = Long.parseLong(matcher.group(3));
tcp_alloc = Long.parseLong(matcher.group(4));
tcp_mem = Long.parseLong(matcher.group(5));
}
break;
case "UDP":
matcher = pattern3.matcher(line);
if (matcher.matches() && matcher.groupCount() == 2) {
udp_inuse = Long.parseLong(matcher.group(1));
udp_mem = Long.parseLong(matcher.group(2));
}
break;
}
}
}
public TreeMap<String, String> getTags() {
return new TreeMap<>();
}
public TreeMap<String, Object> getFields() {
return new TreeMap<String, Object>() {{
put("sockets", sockets);
put("tcp_inuse", tcp_inuse);
put("tcp_alloc", tcp_alloc);
put("tcp_orphan", tcp_orphan);
put("tcp_mem", tcp_mem);
put("tcp_tw", tcp_tw);
put("udp_inuse", udp_inuse);
put("udp_mem", udp_mem);
}};
}
}

View file

@ -1,26 +0,0 @@
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
}
}

View file

@ -1,29 +0,0 @@
import spock.lang.Specification
import sysmon.plugins.os_linux.LinuxSocketExtension
import sysmon.plugins.os_linux.LinuxSocketStat
class LinuxNetworkTest extends Specification {
void "test /proc/net/sockstat parsing"() {
setup:
def testFile = new File(getClass().getResource('/proc_net_sockstat.txt').toURI())
List<String> lines = testFile.readLines("UTF-8")
when:
LinuxSocketExtension extension = new LinuxSocketExtension()
LinuxSocketStat stats = extension.processSockOutput(lines)
then:
stats.getFields().get("sockets") == 1238L
stats.getFields().get("tcp_inuse") == 52L
stats.getFields().get("tcp_orphan") == 0L
stats.getFields().get("tcp_alloc") == 55L
stats.getFields().get("tcp_mem") == 7l
stats.getFields().get("tcp_tw") == 18L
stats.getFields().get("udp_inuse") == 11L
stats.getFields().get("udp_mem") == 10L
}
}

View file

@ -1,112 +0,0 @@
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:

View file

@ -1,6 +0,0 @@
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

View file

@ -1,6 +1,6 @@
# AIX Plugin # IBM Power Plugin
## LPAR Processor Extension ## Power LPAR Processor Extension
The processor extension works for both AIX and Linux on the Power ppc64/ppc64le architecture. The processor extension works for both AIX and Linux on the Power ppc64/ppc64le architecture.

View file

@ -0,0 +1,6 @@
pluginId=sysmon-power
pluginClass=sysmon.plugins.power.PowerPlugin
pluginVersion=0.0.1
pluginProvider=System Monitor
pluginDependencies=
pluginDescription=Collects IBM Power specific metrics.

View file

@ -0,0 +1,18 @@
package sysmon.plugins.power;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.pf4j.Plugin;
import org.pf4j.PluginWrapper;
public class PowerPlugin extends Plugin {
private static final Logger log = LoggerFactory.getLogger(PowerPlugin.class);
public PowerPlugin(PluginWrapper wrapper) {
super(wrapper);
}
}

View file

@ -1,4 +1,4 @@
package sysmon.plugins.os_aix; package sysmon.plugins.power;
import org.pf4j.Extension; import org.pf4j.Extension;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -10,19 +10,17 @@ import sysmon.shared.PluginHelper;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.TreeMap; import java.util.TreeMap;
@Extension @Extension
public class AixProcessorExtension implements MetricExtension { public class PowerProcessorExtension implements MetricExtension {
private static final Logger log = LoggerFactory.getLogger(AixProcessorExtension.class); private static final Logger log = LoggerFactory.getLogger(PowerProcessorExtension.class);
// Extension details // Extension details
private final String name = "aix_processor"; private final String name = "power_processor";
private final String provides = "lpar_processor"; private final String description = "IBM Power Processor Metrics";
private final String description = "AIX Processor Metrics";
// Configuration / Options // Configuration / Options
private boolean enabled = true; private boolean enabled = true;
@ -66,11 +64,6 @@ public class AixProcessorExtension implements MetricExtension {
return interval; return interval;
} }
@Override
public String getProvides() {
return provides;
}
@Override @Override
public String getDescription() { public String getDescription() {
return description; return description;
@ -96,7 +89,7 @@ public class AixProcessorExtension implements MetricExtension {
TreeMap<String, Object> fieldsMap = null; TreeMap<String, Object> fieldsMap = null;
try (InputStream buf = PluginHelper.executeCommand("lparstat 3 1")) { try (InputStream buf = PluginHelper.executeCommand("lparstat 3 1")) {
AixProcessorStat processorStat = processCommandOutput(buf); PowerProcessorStat processorStat = processCommandOutput(buf);
tagsMap = processorStat.getTags(); tagsMap = processorStat.getTags();
fieldsMap = processorStat.getFields(); fieldsMap = processorStat.getFields();
} catch (IOException e) { } catch (IOException e) {
@ -108,8 +101,8 @@ public class AixProcessorExtension implements MetricExtension {
} }
protected AixProcessorStat processCommandOutput(InputStream input) throws IOException { protected PowerProcessorStat processCommandOutput(InputStream input) throws IOException {
return new AixProcessorStat(input); return new PowerProcessorStat(input);
} }
} }

View file

@ -1,4 +1,4 @@
package sysmon.plugins.os_aix; package sysmon.plugins.power;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -8,15 +8,14 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap;
import java.util.Objects; import java.util.Objects;
import java.util.TreeMap; import java.util.TreeMap;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
public class AixProcessorStat { public class PowerProcessorStat {
private static final Logger log = LoggerFactory.getLogger(AixProcessorStat.class); private static final Logger log = LoggerFactory.getLogger(PowerProcessorStat.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 static final Pattern patternAixShared = Pattern.compile("^System configuration: type=(\\S+) mode=(\\S+) smt=(\\d+) lcpu=(\\d+) mem=(\\d+)MB psize=(\\d+) ent=(\\d+\\.?\\d*)"); private static final Pattern patternAixShared = Pattern.compile("^System configuration: type=(\\S+) mode=(\\S+) smt=(\\d+) lcpu=(\\d+) mem=(\\d+)MB psize=(\\d+) ent=(\\d+\\.?\\d*)");
@ -47,7 +46,7 @@ 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.
public AixProcessorStat(InputStream inputStream) throws IOException { public PowerProcessorStat(InputStream inputStream) throws IOException {
String lastLine = null; String lastLine = null;
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));

View file

@ -1,8 +1,8 @@
import sysmon.plugins.os_aix.AixProcessorExtension import sysmon.plugins.power.PowerProcessorExtension
import sysmon.plugins.os_aix.AixProcessorStat import sysmon.plugins.power.PowerProcessorStat
import spock.lang.Specification import spock.lang.Specification
class AixProcessorTest extends Specification { class PowerProcessorTest extends Specification {
void "test AIX lparstat shared output processing"() { void "test AIX lparstat shared output processing"() {
@ -10,8 +10,8 @@ class AixProcessorTest extends Specification {
InputStream inputStream = getClass().getResourceAsStream('/lparstat-aix-shared.txt') InputStream inputStream = getClass().getResourceAsStream('/lparstat-aix-shared.txt')
when: when:
AixProcessorExtension extension = new AixProcessorExtension() PowerProcessorExtension extension = new PowerProcessorExtension()
AixProcessorStat stats = extension.processCommandOutput(inputStream) PowerProcessorStat stats = extension.processCommandOutput(inputStream)
then: then:
stats.getUser() == 83.7f stats.getUser() == 83.7f
@ -30,8 +30,8 @@ class AixProcessorTest extends Specification {
InputStream inputStream = getClass().getResourceAsStream('/lparstat-aix-dedicated-donating.txt') InputStream inputStream = getClass().getResourceAsStream('/lparstat-aix-dedicated-donating.txt')
when: when:
AixProcessorExtension extension = new AixProcessorExtension() PowerProcessorExtension extension = new PowerProcessorExtension()
AixProcessorStat stats = extension.processCommandOutput(inputStream) PowerProcessorStat stats = extension.processCommandOutput(inputStream)
then: then:
stats.getUser() == 0.1f stats.getUser() == 0.1f
@ -51,8 +51,8 @@ class AixProcessorTest extends Specification {
InputStream inputStream = getClass().getResourceAsStream('/lparstat-aix-dedicated-capped.txt') InputStream inputStream = getClass().getResourceAsStream('/lparstat-aix-dedicated-capped.txt')
when: when:
AixProcessorExtension extension = new AixProcessorExtension() PowerProcessorExtension extension = new PowerProcessorExtension()
AixProcessorStat stats = extension.processCommandOutput(inputStream) PowerProcessorStat stats = extension.processCommandOutput(inputStream)
then: then:
stats.getUser() == 0.0f stats.getUser() == 0.0f
@ -71,8 +71,8 @@ class AixProcessorTest extends Specification {
InputStream inputStream = getClass().getResourceAsStream('/lparstat-linux.txt') InputStream inputStream = getClass().getResourceAsStream('/lparstat-linux.txt')
when: when:
AixProcessorExtension extension = new AixProcessorExtension() PowerProcessorExtension extension = new PowerProcessorExtension()
AixProcessorStat stats = extension.processCommandOutput(inputStream) PowerProcessorStat stats = extension.processCommandOutput(inputStream)
then: then:
stats.getUser() == 0.03f stats.getUser() == 0.03f

View file

@ -3,9 +3,9 @@ import org.redline_rpm.header.Os
plugins { plugins {
id 'application' id 'application'
id "com.github.johnrengelman.shadow" version "7.1.2"
id "net.nemerosa.versioning" version "2.15.1" id "net.nemerosa.versioning" version "2.15.1"
id "nebula.ospackage" version "9.1.1" id "com.github.johnrengelman.shadow" version "7.1.2"
id "com.netflix.nebula.ospackage" version "10.0.0"
} }
dependencies { dependencies {
@ -40,7 +40,6 @@ tasks.named('test') {
useJUnitPlatform() useJUnitPlatform()
} }
apply plugin: 'nebula.ospackage'
ospackage { ospackage {
packageName = projectName packageName = projectName
release = '1' release = '1'

View file

@ -9,6 +9,7 @@
plugins { plugins {
id 'groovy' id 'groovy'
id 'java-library' id 'java-library'
id 'maven-publish'
} }
repositories { repositories {
@ -33,3 +34,24 @@ tasks.named('test') {
// Use junit platform for unit tests. // Use junit platform for unit tests.
useJUnitPlatform() useJUnitPlatform()
} }
publishing {
publications {
library(MavenPublication) {
groupId = 'sysmon'
artifactId = 'shared'
from components.java
}
}
repositories {
maven {
name = "gitea"
url = uri("https://git.data.coop/api/packages/$System.env.DRONE_REPO_OWNER/maven")
credentials {
username = "$System.env.DRONE_REPO_OWNER"
password = "$System.env.AUTH_TOKEN"
}
}
}
}

View file

@ -12,7 +12,6 @@ public interface MetricExtension extends ExtensionPoint {
String getName(); String getName();
String getInterval(); String getInterval();
String getProvides();
String getDescription(); String getDescription();
void setConfiguration(Map<String, Object> map); void setConfiguration(Map<String, Object> map);

View file

@ -0,0 +1,7 @@
package sysmon.shared;
public interface MetricScript {
MetricResult getMetrics();
}