Skip to content

Commit

Permalink
Lots of little clean-up bits, readying for next release.
Browse files Browse the repository at this point in the history
Jackson annotations all turned out to be superfluous... who knew?
  • Loading branch information
sschwartzman committed Jun 7, 2019
1 parent 62fccb0 commit 7d3c56a
Show file tree
Hide file tree
Showing 12 changed files with 84 additions and 205 deletions.
25 changes: 25 additions & 0 deletions Sample_NRQL_README.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<h1><a href="#sample-nrql-queries" id="sample-nrql-queries"></a>Sample NRQL Queries</h1>
<p>The following are sample NRQL queries that can be used to configure alerts/widgets in dashboards</p>
<p>*<strong>The NRQL queries suggested here only serve as examples, they need to be modified as per deployments</strong></p>
<table>
<thead>
<tr><th>Resource</th><th>AIX command</th><th>Description</th><th>Sample NRQL</th></tr>
</thead>
<tbody>
<tr><td>CPU Usage</td><td>lparstat 1 1</td><td>This situation monitors the overall CPU utilization of the server</td><td>SELECT average(`cpu.system`)from `unixMonitor:Stats` FACET hostname </td></tr>
<tr><td>File Space Fragmented</td><td>df -v -k</td><td>This situation monitors for inodes High and file system used Low, then indicates that file space is fragmented for WARNING severity</td><td>SELECT average(inodesPercentUsed) FROM `unixMonitor:Disk` WHERE mountPoint='/usr' AND hostname='b01avi11810417'</td></tr>
<tr><td>File System Percent - All</td><td> df -v -k</td><td>File System usage</td><td>SELECT average(used) FROM `unixMonitor:Disk` AND hostname='b01avi11810417'</td></tr>
<tr><td>File System Percent - Specified File Systems</td><td>df -v -k</td><td>This situation monitors all OS-related filesystems on an Unix system with MINOR severity</td><td>SELECT average(used) FROM `unixMonitor:Disk` WHERE mountPoint = '/opt' AND hostname='b01avi11810417'</td></tr>
<tr><td>Inodes Percent</td><td>df -v -k</td><td>This situation monitors ALL mounted File system's Inodes % used on AIX system for MINOR severity</td><td>SELECT average(inodesPercentUsed) FROM `unixMonitor:Disk WHERE hostname='b01avi11810417'</td></tr>
<tr><td>Process CPU Usage</td><td>ps vewwwg</td><td>This situation monitors the CPU percent utilization at 95% by all processes except kproc and swapper for WARNING Severity</td><td>SELECT average(cpu) from `unixMonitor:Process` WHERE instance NOT LIKE '%kproc%' AND instance NOT LIKE 'swapper' AND hostname='b01avi11810417'</td></tr>
<tr><td>Process Missing</td><td>ps vewwwg</td><td>This situation detects if a critical OS-related process is not running</td><td>SELECT uniqueCount(pid) from `unixMonitor:Process` WHERE instance='cimserver' AND hostname='b01avi11810417'</td></tr>
<tr><td>Process User</td><td>ps vewwwg</td><td>This situation detects if the MQ ITM agent is running as root</td><td>SELECT uniqueCount(pid) from `unixMonitor:Process` WHERE instance = 'cimlistener' AND command LIKE '%LOGNAME=root%' AND hostname='b01avi11810417'</td></tr>
<tr><td>Swap Percent</td><td>svmon -Ounit=KB</td><td>This situation monitors swap space availability</td><td>select average(`swap.total`-`swap.used`) as 'Avg Swap.Free' from `unixMonitor:Stats' WHERE hostname='b01avi11810417'</td></tr>
<tr><td>Zombie Processes</td><td>ps vewwwg</td><td>This situation searches for the total amount of zombie processes running</td><td>SELECT uniquecount(state) FROM `unixMonitor:Process` WHERE state='Z' AND hostname='b01avi11810417'</td></tr>
<tr><td>Errpt Errors </td><td> errpt </td><td>Entries of CLASS Hardware with TYPE of PEND or PERM in errpt or a particular message</td><td>SELECT uniqueCount(instance) from `unixMonitor:Errpt` where class='S' and type='P' FACET hostname </td></tr>
<tr><td>Backup errors</td><td> lsmksysb -B</td><td> errors encountered during backup</td><td> SELECT uniqueCount(`orignal.date`) FROM `unixMonitor:Backup` WHERE device='/mksysbimg/mksysb.b01avi11810415.aix710.123018' AND command LIKE '%error%' AND hostname='b01avi11810417'</td></tr>
<tr><td>Ethernet Channel Errors</td><td>entstat 'device'</td><td>Monitors for Ethernet Errors</td><td>select uniqueCount(instance)from `unixMonitor:NetworkIO` WHERE `receive.errors` &gt;0 OR `transmit.errors`&gt;0 AND hostname='b01avi11810417'</td></tr>
<tr><td>File exists</td><td>ls -l</td><td> checks availability of the configured file </td><td>select uniqueCount(`file.date`) from `unixMonitor:File` WHERE `file.path`='/opt/New_Relic/newrelic-unix-monitor/config/plugin.json' FACET hostname </td></tr>
<tr><td colspan="3"></td></tr>
</tbody>
</table>
4 changes: 2 additions & 2 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.newrelic.experts</groupId>
<artifactId>newrelic-unix-monitor</artifactId>
<version>0.1.41</version>
<version>0.1.5</version>
<name>newrelic-unix-monitor</name>
<build>
<plugins>
Expand Down Expand Up @@ -67,7 +67,7 @@
<dependency>
<groupId>com.newrelic.experts</groupId>
<artifactId>infra_publish</artifactId>
<version>2.2.0</version>
<version>2.2.1</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,9 @@ else if (columnMetricName.equals(UnixAgentConstants.kColumnMetricName)) {
}

// Metric prefixes get appended to the "Instance" attribute.
else if (columnMetricName.equals(UnixAgentConstants.kColumnMetricPrefix)) {
// Can be "METRIC_PREFIX" (old syntax) or "METRIC_INSTANCE" (new syntax) - yay backwards compatibility!
else if (columnMetricName.equals(UnixAgentConstants.kColumnMetricPrefix) ||
columnMetricName.equals(UnixAgentConstants.kColumnMetricInstance)) {
thisMetricInstance = mungeString(thisMetricInstance, thisColumn,
UnixAgentConstants.kMetricTreeDivider);
}
Expand Down
95 changes: 39 additions & 56 deletions src/main/java/com/newrelic/infra/unix/UnixAgent.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,69 +23,54 @@ public class UnixAgent extends Agent {
private HashSet<String> disks;
private HashSet<String> networkInterfaces;
private int pageSize;

private Map<String, Long> commandtimestamp;

private Map<String, Long> commandTimestamp;

public UnixAgent(AgentSettings asettings) {
agentSettings = asettings;
disks = getMembers(agentSettings.getOsSettings().getDisksCommand(), agentSettings.getOsSettings().getDisksRegex());
networkInterfaces = getMembers(agentSettings.getOsSettings().getInterfacesCommand(), agentSettings.getOsSettings().getInterfacesRegex());
setPageSize(agentSettings);
addStaticAttribute(UnixAgentConstants.KAOSMetricName, agentSettings.getOs().split("_")[0]);
commandtimestamp = new HashMap();
commandTimestamp = new HashMap();
}

private boolean doruncommand(Command command) {
// Maintain timestamp for when the command was run last. we will skip the
// commands unless its time for them to run
// added interval attribute in the command json.
// Check if we have entry for command if not

// Check if the command interval is configured, if not return true to run for
// each poll cycle

long interval = 0;
if (command.getInterval() != null) {
// convert interval to milliseconds
interval = command.getInterval() * 60000;
// Maintain timestamp for when the command was run last.
// If the command has an interval established ("'interval': nnn" in plugin-commands-xxx.json),
// only run command where the interval has been exceeded since the last run.
// Returns 'true' if the command should be run, 'false' if it should be skipped.
private boolean doRunCommand(Command command) {
// Check if the command interval is non-zero (default is 0).
// If 0, don't bother doing anything else and return true.
if(command.getInterval() == 0) {
logger.debug("doRunCommand: Interval not configured or set to '0' for command "
+ command.getCommand() + ", will always execute.");
return true;
}

String commmandtoexecute = command.getCommand();

String commandExec = command.getCommand();
long interval = command.getInterval() * 60000;
long currentTime = System.currentTimeMillis();

// Check if the command interval is configured, if not return true to run for
// each poll cycle
if (interval != 0) {
if (commandtimestamp.containsKey(commmandtoexecute)) {
// Find the last run timestamp
long lastrun = commandtimestamp.get(commmandtoexecute);
// Check if it is time to execute the command
if ((currentTime - lastrun) > interval) {
// Update the timestamp
logger.debug("doruncommand: Time to run command " + commmandtoexecute + " Interval@ " + interval);
commandtimestamp.put(commmandtoexecute, currentTime);
return true;
} else {
// Skip running command since interval has not passed
logger.debug(
"doruncommand: Skipping command " + commmandtoexecute + " Timeleft@ " + (currentTime - lastrun) +" Interval@ " + interval);
return false;
}

} else {
// First run, since there is interval we need to maintain map
logger.debug("doruncommand: First run for command " + commmandtoexecute + " @ " + currentTime);
commandtimestamp.put(commmandtoexecute, currentTime);
if (commandTimestamp.containsKey(commandExec)) {
// Find the last run timestamp
long lastrun = commandTimestamp.get(commandExec);
// Check if it is time to execute the command
if ((currentTime - lastrun) > interval) {
// Update the timestamp
logger.debug("doRunCommand: Time to run command " + commandExec + ", Interval @ " + interval);
commandTimestamp.put(commandExec, currentTime);
return true;
} else {
// Skip running command since interval has not passed
logger.debug("doRunCommand: Skipping command " + commandExec +
", Timeleft @ " + (currentTime - lastrun) + ", Interval @ " + interval);
return false;
}

}
{
logger.debug("doruncommand: No interval configured for command " + commmandtoexecute);
} else {
// First run, since there is interval we need to maintain map
logger.debug("doRunCommand: First run for command " + commandExec + " @ " + currentTime);
commandTimestamp.put(commandExec, currentTime);
return true;
}

}

@Override
Expand All @@ -106,14 +91,13 @@ public void populateMetrics(MetricReporter metricReporter) throws Exception {
members.add("");
}

// We need a hack to not run all the commands every harvest cycle. In cases where we just need to run commands every day or even once a week.
if( doruncommand(command))
{
// Checks whether to run this commands in this harvest cycle.
if(doRunCommand(command)) {
for(String thisMember : members) {
CommandMetricUtils.parseCommandOutput(command, thisMember, metricReporter, getStaticAttributes(), pageSize);
}
}else {
logger.debug("Info: Skipping " + command.getEventType() + " : " + command.getCommand() );
} else {
logger.debug("Info: Skipping " + command.getEventType() + " : " + command.getCommand());
}
} catch (Exception e) {
logger.error("Error: Parsing of " + command.getEventType() + " : " + command.getCommand() + " could not be completed.");
Expand Down Expand Up @@ -159,9 +143,8 @@ public void setPageSize(AgentSettings agentSettings) {
}

@Override
public void dispose() throws Exception {
}
public void dispose() throws Exception { }

@Override
public void populateInventory(InventoryReporter inventoryReporter) throws Exception { }
public void populateInventory(InventoryReporter inventoryReporter) throws Exception { }
}
2 changes: 2 additions & 0 deletions src/main/java/com/newrelic/infra/unix/UnixAgentConstants.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ public final class UnixAgentConstants {
public static final String kColumnMetricDiskName = "DISK_NAME";
public static final String kColumnIgnore = "IGNORE_COLUMN";
public static final String kColumnMetricName = "METRIC_NAME";
// METRIC_INSTANCE and METRIC_PREFIX are interchangeable
public static final String kColumnMetricInstance = "METRIC_INSTANCE";
public static final String kColumnMetricPrefix = "METRIC_PREFIX";
public static final String kColumnMetricValue = "METRIC_VALUE";
public static final String kColumnMetricProcessName = "PROCESS_NAME";
Expand Down
3 changes: 0 additions & 3 deletions src/main/java/com/newrelic/infra/unix/UnixAgentFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,7 @@ public Agent createAgent(Map<String, Object> properties) throws Exception {

String commandsFileName = properties.containsKey("configDir") ? (String) properties.get("configDir") : "./config";
commandsFileName += File.separator + "plugin-commands-" + os + ".json";

File commandsFile = new File(commandsFileName);

AgentSettings agentSettings = new AgentSettings();

if (commandsFile.exists()) {
Expand All @@ -75,7 +73,6 @@ public Agent createAgent(Map<String, Object> properties) throws Exception {
agentSettings.setOs(os);
agentSettings.setHostname(hostname);
agentSettings.setAgentname(agentname);

return new UnixAgent(agentSettings);
}

Expand Down
14 changes: 1 addition & 13 deletions src/main/java/com/newrelic/infra/unix/config/AgentSettings.java
Original file line number Diff line number Diff line change
@@ -1,37 +1,25 @@

package com.newrelic.infra.unix.config;

import java.util.List;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;

@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonPropertyOrder({
"os_settings",
"commands"
})
import com.fasterxml.jackson.annotation.JsonProperty;

public class AgentSettings {
@JsonProperty("os_settings")
private OsSettings osSettings;
@JsonProperty("commands")
private List<Command> commands = null;
private String os = null;
private String hostname = null;
private String agentname = null;

@JsonProperty("os_settings")
public OsSettings getOsSettings() {
return osSettings;
}

@JsonProperty("os_settings")
public void setOsSettings(OsSettings osSettings) {
this.osSettings = osSettings;
}

@JsonProperty("commands")
public List<Command> getCommands() {
return commands;
}
Expand Down
43 changes: 8 additions & 35 deletions src/main/java/com/newrelic/infra/unix/config/Command.java
Original file line number Diff line number Diff line change
@@ -1,93 +1,66 @@

package com.newrelic.infra.unix.config;

import java.util.List;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;

import com.newrelic.infra.unix.CommandMetricUtils;
import com.newrelic.infra.unix.UnixAgentConstants;

@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonPropertyOrder({
"eventType",
"command",
"checkAllRegex",
"lineLimit",
"interval",
"mappings"
})
public class Command {

@JsonProperty("eventType")
// "Required" fields
private String eventType;
@JsonProperty("command")
private String command;
@JsonProperty("checkAllRegex")
private Boolean checkAllRegex;
@JsonProperty("lineLimit")
private Integer lineLimit;
@JsonProperty("mappings")
private List<CommandMapping> mappings = null;
@JsonProperty("interval")
private Integer interval;

// "Optional" fields (have a default value)
private Boolean checkAllRegex = false;
private Integer interval = 0;
private Integer lineLimit = 0;

@JsonProperty("eventType")
public String getEventType() {
return eventType;
}

@JsonProperty("eventType")
public void setEventType(String type) {
this.eventType = CommandMetricUtils.mungeString(UnixAgentConstants.kEventTypePrefix, type, ':');
this.eventType = CommandMetricUtils.mungeString(UnixAgentConstants.kEventTypePrefix, type, ':');
}

@JsonProperty("command")
public String getCommand() {
return command;
}

@JsonProperty("command")
public void setCommand(String command) {
this.command = command;
}

@JsonProperty("checkAllRegex")
public Boolean getCheckAllRegex() {
return checkAllRegex;
}

@JsonProperty("checkAllRegex")
public void setCheckAllRegex(Boolean checkAllRegex) {
this.checkAllRegex = checkAllRegex;
}

@JsonProperty("lineLimit")
public Integer getLineLimit() {
return lineLimit;
}

@JsonProperty("lineLimit")
public void setLineLimit(Integer lineLimit) {
this.lineLimit = lineLimit;
}

@JsonProperty("mappings")
public List<CommandMapping> getMappings() {
return mappings;
}

@JsonProperty("mappings")
public void setMappings(List<CommandMapping> mappings) {
this.mappings = mappings;
}

@JsonProperty("interval")
public Integer getInterval() {
return interval;
}

@JsonProperty("interval")
public void setInterval(Integer interval) {
this.interval = interval;
}
Expand Down
Loading

0 comments on commit 7d3c56a

Please sign in to comment.