diff --git a/build.gradle b/build.gradle index cbbd04b..8d3ec56 100644 --- a/build.gradle +++ b/build.gradle @@ -5,7 +5,7 @@ plugins { } group = 'com.newrelic.labs' -version = '' +version = '1.1' repositories { mavenCentral() diff --git a/config/softwareag-ums-server-config.json b/config/softwareag-ums-server-config.json index 15a8352..0f0e5b9 100644 --- a/config/softwareag-ums-server-config.json +++ b/config/softwareag-ums-server-config.json @@ -1,15 +1,16 @@ { "instances": [ { - "name": "SoftwareAG-UME-SERVER-1", + "name": "SoftwareAG-UMS-Realm", "host": "localhost", "port": 9000, "username": "myuser4", "password": "mypwd4", - "encryptPassword": false + "encryptPassword": false, + "isCluster": false }, { - "name": "SoftwareAG-UME-SERVER-2", + "name": "SoftwareAG-UMS-Cluster", "host": "localhost", "port": 9001, "username": "myuser4", diff --git a/lib/umTools.jar b/lib/umTools.jar new file mode 100755 index 0000000..5cb1fbf Binary files /dev/null and b/lib/umTools.jar differ diff --git a/src/main/java/com/newrelic/nri/softwareag/ums/ClusterState.java b/src/main/java/com/newrelic/nri/softwareag/ums/ClusterState.java new file mode 100644 index 0000000..f8f0bfa --- /dev/null +++ b/src/main/java/com/newrelic/nri/softwareag/ums/ClusterState.java @@ -0,0 +1,316 @@ +package com.newrelic.nri.softwareag.ums; + +import com.pcbsys.nirvana.client.nIllegalArgumentException; +import com.pcbsys.nirvana.client.nRealmUnreachableException; +import com.pcbsys.nirvana.client.nSessionAttributes; +import com.pcbsys.nirvana.nAdminAPI.nBaseAdminException; +import com.pcbsys.nirvana.nAdminAPI.nClusterNode; +import com.pcbsys.nirvana.nAdminAPI.nClusterSite; +import com.pcbsys.nirvana.nAdminAPI.nClusterStatus; +import com.pcbsys.nirvana.nAdminAPI.nClusterStatusEntry; +import com.pcbsys.nirvana.nAdminAPI.nRealmNode; +import com.softwareag.um.tools.ErrorCodes; +import com.softwareag.um.tools.UMToolCommon; +import com.softwareag.um.tools.UMToolInterface; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; +import java.util.Map.Entry; +import java.util.logging.Logger; + +public class ClusterState implements UMToolInterface { + private static final String RNAME = "rname"; + private static final String COLUMN_DELIMITER = " | "; + private static final String WHITESPACE = " "; + private static final String SERVER_NAME_STR = "| Server Name"; + private static final String RNAMES_STR = "| Rnames"; + private static final String IS_CLUSTERED_STR = "| Is Clustered"; + private static final String SERVER_STATUS_STR = "| Server Status"; + private static final String CLUSTER_STATE_STR = "| Cluster State"; + private static final String BROADCAST_TIME_STR = "| Broadcast Time"; + private static final String CLIENT_REQUEST_SIZE_STR = "| Client Request Size"; + private static final String COMMS_QUEUE_SIZE_STR = "| Comms Queue Size"; + private static final String QUEUE_SIZE_STR = "| Queue Size"; + private static final String RESPONSE_TIME_STR = "| Response Time"; + nClusterNode clusterNode = null; + nRealmNode realm = null; + nRealmNode masterNode = null; + private String rName; + private Logger logger; + + public static void main(String[] var0) + throws nIllegalArgumentException, nBaseAdminException, nRealmUnreachableException { + UMToolCommon.executeTool(new ClusterState(), var0, false); + } + + public String getToolName() { + return "ClusterState"; + } + + public String getToolDescription() { + return this.getToolName() + "Checks the cluster state by a give RNAME , which is part of a cluster"; + } + + public String[] getToolExamples() { + return new String[]{this.getToolName() + " -rname=nsp://localhost:9000"}; + } + + public String getToolCategory() { + return "2. Cluster tools"; + } + + public String[] getToolArgumentsRequired() { + return new String[]{"rname"}; + } + + public String[] getToolArgumentsOptional() { + return new String[0]; + } + + public String getNormalisedParameter(String var1) { + return "rname".equalsIgnoreCase(var1) ? "rname" : var1; + } + + public String getParameterDescription(String var1) { + return var1.equals("rname") ? "Name of a realm , which is part of a cluster" : "Unknown Parameter"; + } + + public void initialise(Map var1, Logger var2) throws Exception { + this.logger = var2; + this.rName = (String) var1.remove("rname"); + if (!var1.isEmpty()) { + byte var3 = 32; + var2.severe( + ErrorCodes.getErrorContext(var3, (String) ((Entry) var1.entrySet().iterator().next()).getKey())); + UMToolCommon.exit(var3); + } + + this.logger.fine("We have initialised " + this.getToolName() + " with: " + this.rName); + } + + public void execute() throws Exception { + int var1 = this.getLengthOfLongest("| Server Name", "| Rnames", "| Is Clustered", "| Server Status", + "| Cluster State", "| Broadcast Time", "| Client Request Size", "| Comms Queue Size", "| Queue Size", + "| Response Time"); + ArrayList var2 = new ArrayList(); + ArrayList var3 = new ArrayList(); + ArrayList var4 = new ArrayList(); + ArrayList var5 = new ArrayList(); + ArrayList var6 = new ArrayList(); + ArrayList var7 = new ArrayList(); + ArrayList var8 = new ArrayList(); + ArrayList var9 = new ArrayList(); + ArrayList var10 = new ArrayList(); + ArrayList var11 = new ArrayList(); + + try { + this.realm = UMToolCommon.createRealmNode(new nSessionAttributes(this.rName)); + if (this.realm != null) { + this.realm.waitForEntireNameSpace(5000L); + this.clusterNode = this.realm.getCluster(); + if (this.clusterNode != null) { + this.logger.info("--------------------------------------"); + this.logger.info("Cluster Name: " + this.clusterNode.getName()); + this.logger.info("--------------------------------------"); + Enumeration var12 = this.clusterNode.getNodes(); + this.masterNode = this.clusterNode.getMaster(); + + int var16; + while (var12.hasMoreElements()) { + nRealmNode var13 = (nRealmNode) var12.nextElement(); + var2.add(var13.getName()); + StringBuilder var14 = new StringBuilder(); + String[] var15 = var13.getRealm().getProtocols(); + var16 = var15.length; + + for (int var17 = 0; var17 < var16; ++var17) { + String var18 = var15[var17]; + var14.append(var18 + " "); + } + + var3.add(var14.toString().replace(" ", "\n")); + var4.add(var13.isClustered()); + } + + this.logger.info("Cluster Statuses: "); + Iterator var22 = this.clusterNode.getClusterConnectionStatus().iterator(); + + while (var22.hasNext()) { + Object var24 = var22.next(); + nClusterStatus var26 = (nClusterStatus) var24; + nClusterStatusEntry var28 = var26.getStatus(var26.getName()); + if (var28 != null) { + var5.add(var28.isOnline() ? "online" : "offline"); + var6.add(var26.getState()); + var7.add(var28.getBroadcastTime()); + var8.add(var28.getClientRequestSize()); + var9.add(var28.getCommsQueueSize()); + var10.add(var28.getQueueSize()); + var11.add(var28.getResponseTime()); + } + } + + int[] var23 = new int[var2.size() + 1]; + var23[0] = var1; + + int var25; + for (var25 = 0; var25 < var2.size(); ++var25) { + var23[var25 + 1] = this.getLengthOfLongest(var2.get(var25), var4.get(var25), var5.get(var25), + var6.get(var25), var7.get(var25), var8.get(var25), var9.get(var25), var10.get(var25), + var11.get(var25)); + } + + var25 = 0; + + for (int var27 = 0; var27 < var23.length; ++var27) { + var25 += var23[var27]; + } + + StringBuilder var29 = new StringBuilder(); + var25 += " | ".length() * var23.length - 1; + var29.append(this.getFence(var25)); + var29.append("\n"); + var29.append(this.getResultLine(var23, "| Server Name", var2)); + var29.append(this.getResultLine(var23, "| Is Clustered", var4)); + var29.append(this.getResultLine(var23, "| Server Status", var5)); + var29.append(this.getResultLine(var23, "| Cluster State", var6)); + var29.append(this.getResultLine(var23, "| Broadcast Time", var7)); + var29.append(this.getResultLine(var23, "| Client Request Size", var8)); + var29.append(this.getResultLine(var23, "| Comms Queue Size", var9)); + var29.append(this.getResultLine(var23, "| Queue Size", var10)); + var29.append(this.getResultLine(var23, "| Response Time", var11)); + var29.append(this.getFence(var25)); + var29.append("\n"); + + for (var16 = 0; var16 < var3.size(); ++var16) { + var29.append(var2.get(var16) + " Protocols:\n"); + var29.append(var3.get(var16) + "\n"); + } + + this.logger.info(var29.toString()); + this.logger.info("Remote Cluster Connections"); + this.logger.info("--------------------------------------"); + Set var30 = this.clusterNode.getKnownRemoteClusters(); + Iterator var31; + if (var30.isEmpty()) { + this.logger.info("No remote cluster connections have been found"); + } else { + this.logger.info("The following remote cluster connections have been found:"); + var31 = var30.iterator(); + + while (var31.hasNext()) { + nClusterNode var32 = (nClusterNode) var31.next(); + this.logger.info("Cluster name: " + var32.getName()); + } + } + + this.logger.info("--------------------------------------"); + this.logger.info("Cluster Sites"); + this.logger.info("--------------------------------------"); + var31 = this.clusterNode.getSites(); + if (var31 != null && var31.hasNext()) { + while (var31.hasNext()) { + nClusterSite var33 = (nClusterSite) var31.next(); + if (var33 != null) { + this.logger.info("Site name: " + var33.getName()); + this.logger.info("Is prime: " + var33.isPrime()); + } + } + } else { + this.logger.info("There are no sites in the cluster"); + } + + this.logger.fine(this.getToolName() + " has now executed"); + } else { + this.logger.info("The provided RNAME is not part of a cluster"); + } + } else { + this.logger.info("There is no reachable realm with this RNAME"); + } + } finally { + if (this.masterNode != null) { + this.masterNode.close(); + } + + if (this.realm != null) { + this.realm.close(); + } + + if (this.clusterNode != null) { + this.clusterNode.close(); + } + + } + + } + + private String getFence(int var1) { + StringBuilder var2 = new StringBuilder(); + + for (int var3 = 0; var3 < var1; ++var3) { + var2.append("-"); + } + + return var2.toString(); + } + + private String getResultLine(int[] var1, String var2, ArrayList var3) { + var3.add(0, var2); + StringBuilder var4 = new StringBuilder(); + + for (int var5 = 0; var5 < var3.size(); ++var5) { + Object var6 = var3.get(var5); + var4.append(var6.toString()); + var4.append(this.getWhitespaces(var1[var5] - var6.toString().length())); + var4.append(" | "); + } + + var4.append("\n"); + var3.remove(0); + return var4.toString(); + } + + private String getWhitespaces(int var1) { + StringBuilder var2 = new StringBuilder(); + + for (int var3 = 0; var3 < var1; ++var3) { + var2.append(" "); + } + + return var2.toString(); + } + + private int getLengthOfLongest(Object... var1) { + int var2 = 0; + Object[] var3 = var1; + int var4 = var1.length; + + for (int var5 = 0; var5 < var4; ++var5) { + Object var6 = var3[var5]; + String var7 = var6.toString(); + if (var2 < var7.length()) { + var2 = var7.length(); + } + } + + return var2; + } + + public void close() throws Exception { + if (this.masterNode != null) { + this.masterNode.close(); + } + + if (this.realm != null) { + this.realm.close(); + } + + if (this.clusterNode != null) { + this.clusterNode.close(); + } + + this.logger.fine("We have now have cleaned up"); + } +} \ No newline at end of file diff --git a/src/main/java/com/newrelic/nri/softwareag/ums/JSONMetricReporter.java b/src/main/java/com/newrelic/nri/softwareag/ums/JSONMetricReporter.java index e5065af..f8ebf5b 100644 --- a/src/main/java/com/newrelic/nri/softwareag/ums/JSONMetricReporter.java +++ b/src/main/java/com/newrelic/nri/softwareag/ums/JSONMetricReporter.java @@ -16,9 +16,9 @@ public class JSONMetricReporter { - private static final String NAME = "SoftwareagUME"; + private static final String NAME = "SoftwareagUMS"; private static final String PROTOCOL_VERSION = Integer.toString(2); - private static final String INTEGRATION_VERSION = "1.0"; + private static final String INTEGRATION_VERSION = "1.1"; private Map> values = new HashMap<>(); private List data = new ArrayList<>(); diff --git a/src/main/java/com/newrelic/nri/softwareag/ums/Main.java b/src/main/java/com/newrelic/nri/softwareag/ums/Main.java index 2bd7268..742756a 100644 --- a/src/main/java/com/newrelic/nri/softwareag/ums/Main.java +++ b/src/main/java/com/newrelic/nri/softwareag/ums/Main.java @@ -39,7 +39,7 @@ public static void main(String[] argv) { } String configFile = System.getenv("CONFIG_FILE"); - //String configFile = "/Users/gsidhwani/Documents/GitHub/SoftwareAG/softwareag-ume-server-config.json"; + //String configFile = "/Users/gsidhwani/Documents/GitHub/SoftwareAG/softwareag-ume-server-config.json"; if (configFile == null) { configFile = args.getConfigFile(); @@ -134,16 +134,30 @@ public void setup(String pluginConfigFileName) throws Exception { } try { - UMSMonitorFactory factory = new UMSMonitorFactory(); - UMSMonitor monitor = factory.createAgent(agentProperties); - JSONMetricReporter metricReporter = new JSONMetricReporter(); - monitor.populateMetrics(metricReporter); - JSONObject reportJson = metricReporter.getJSON(); - String jsonStr = reportJson.toString(); - System.out.println(jsonStr); + UMSMonitorFactory factory = new UMSMonitorFactory(); + + Object monitor = factory.createAgent(agentProperties); + JSONMetricReporter metricReporter = new JSONMetricReporter(); + + if (monitor instanceof UMSClusterMonitor) { + ((UMSClusterMonitor) monitor).populateMetrics(metricReporter); + // System.out.println("Processing as Cluster."); + + } else if (monitor instanceof UMSMonitor) { + ((UMSMonitor) monitor).populateMetrics(metricReporter); + // System.out.println("Processing as Realm."); + } else { + // Handle the case when 'monitor' is neither UMSClusterMonitor nor UMSMonitor + // System.out.println("Unknown monitor type."); + + } + + JSONObject reportJson = metricReporter.getJSON(); + String jsonStr = reportJson.toString(); + System.out.println(jsonStr); } catch (Exception e) { - e.printStackTrace(); - Utils.reportError("Error occurred while getting metrics",e); + e.printStackTrace(); + Utils.reportError("Error occurred while getting metrics", e); } } diff --git a/src/main/java/com/newrelic/nri/softwareag/ums/StatType.java b/src/main/java/com/newrelic/nri/softwareag/ums/StatType.java index 4777a1c..3646de3 100644 --- a/src/main/java/com/newrelic/nri/softwareag/ums/StatType.java +++ b/src/main/java/com/newrelic/nri/softwareag/ums/StatType.java @@ -7,6 +7,12 @@ public String getEventType() { return "UMSChannel"; } }, + Cluster { + @Override + public String getEventType() { + return "UMSCluster"; + } + }, Bridge { @Override public String getEventType() { diff --git a/src/main/java/com/newrelic/nri/softwareag/ums/UMSCluster.java b/src/main/java/com/newrelic/nri/softwareag/ums/UMSCluster.java new file mode 100644 index 0000000..0fa3d73 --- /dev/null +++ b/src/main/java/com/newrelic/nri/softwareag/ums/UMSCluster.java @@ -0,0 +1,244 @@ +package com.newrelic.nri.softwareag.ums; + +/* +* +* Copyright (c) 1999 - 2011 my-Channels Ltd +* Copyright (c) 2012 - 2022 Software AG, Darmstadt, Germany and/or Software AG USA Inc., Reston, VA, USA, and/or its subsidiaries and/or its affiliates and/or their licensors. +* +* Use, reproduction, transfer, publication or disclosure is prohibited except as specifically provided for in your License Agreement with Software AG. +* +*/ + +import com.pcbsys.nirvana.client.nChannel; +import com.pcbsys.nirvana.client.nChannelAttributes; +import com.pcbsys.nirvana.client.nChannelNotFoundException; +import com.pcbsys.nirvana.client.nConsumeEvent; +import com.pcbsys.nirvana.client.nSessionAttributes; +import com.pcbsys.nirvana.client.nSessionNotConnectedException; +import com.pcbsys.nirvana.nAdminAPI.nClusterEventListener; +import com.pcbsys.nirvana.nAdminAPI.nClusterNode; +import com.pcbsys.nirvana.nAdminAPI.nClusterStatus; +import com.pcbsys.nirvana.nAdminAPI.nClusterStatusEntry; +import com.pcbsys.nirvana.nAdminAPI.nNode; +import com.pcbsys.nirvana.nAdminAPI.nRealmNode; +import java.util.Date; +import java.util.Enumeration; +import java.util.Observable; +import java.util.Observer; +import java.util.Vector; + +public class UMSCluster implements nClusterEventListener, Observer { + + // The realm node to connect to + private nRealmNode myRealm; + + + /** + * Construct the cluster watch object using the RNAME of the realm to connect to + * + * @param args arg[0] should be the RNAME + */ + public UMSCluster(String[] args) throws Exception { + myRealm = new nRealmNode(new nSessionAttributes(args[0])); + myRealm.waitForEntireNameSpace(40000); + if (!myRealm.isClustered()) { + System.out.println("Node is not part of a cluster"); + System.exit(1); + } + // add observer to the realm to get new cluster notifications + nClusterNode cNode = myRealm.getCluster(); + Vector myRealms = new Vector(); + if (cNode != null) { + report("Starting cluster monitor...."); + cNode.addListener(this); + cNode.addObserver(this); + + nChannelAttributes ca = new nChannelAttributes("ClusterMonitor", 10, 0, nChannelAttributes.RELIABLE_TYPE); + try { + myRealm.getSession().findChannel(ca); + } catch (nChannelNotFoundException e) { + myRealm.getSession().createChannel(ca); + } + + Enumeration enm = cNode.getNodes(); + while (enm.hasMoreElements()) { + nNode node = (nNode) enm.nextElement(); + if (node instanceof nRealmNode) { + myRealms.add(new RealmMonitor((nRealmNode) node)); + } + } + while (true) { + Thread.sleep(31000); + StringBuilder usage = new StringBuilder(); + for (int x = 0; x < myRealms.size(); x++) { + RealmMonitor mon = (RealmMonitor) myRealms.elementAt(x); + usage.append(mon.getRealmName()).append(" Mem ") + .append(((int) ((mon.getNode().getFreeMemory() * 100) / (mon.getNode().getTotalMemory())))) + .append("% free, "); + } + report("Monitoring...." + usage.toString()); + for (int x = 0; x < myRealms.size(); x++) { + RealmMonitor mon = (RealmMonitor) myRealms.elementAt(x); + for (int y = x; y < myRealms.size(); y++) { + RealmMonitor mon2 = (RealmMonitor) myRealms.elementAt(y); + if (mon.getLastEID() != mon2.getLastEID()) { + StringBuilder buf = new StringBuilder(); + buf.append(mon.getRealmName()).append(" doesn't match ").append(mon2.getRealmName()).append(" ") + .append(mon.getLastEID()).append(" != ").append(mon2.getLastEID()); + report(buf.toString()); + } + } + } + Vector tmp = myRealm.getCluster().getClusterConnectionStatus(); + for (int x = 0; x < tmp.size(); x++) { + nClusterStatus cs = (nClusterStatus) tmp.elementAt(x); + if (!(cs.getState().equalsIgnoreCase("Master") || cs.getState().equalsIgnoreCase("Slave"))) { + report("Cluster has not fully formed..." + cs.getName() + " " + cs.getState()); + } + } + } + } + } + + public static void main(String[] args) { + try { + new UMSCluster(args); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + /** + * New member added to the cluster + */ + public void memberAdded(nRealmNode node) { + report("Member added to cluster " + node.getName()); + } + + /** + * Member deleted from the cluster + */ + public void memberDeleted(nRealmNode node) { + report("Member deleted from cluster " + node.getName()); + } + + /** + * quorum reached, i.e. master realm has been elected + */ + public void quorumReached(nRealmNode masterNode) { + report("quorum reach, master - " + masterNode.getName()); + } + + /** + * quorum lost, i.e. master realm has been lost, no current master + */ + public void quorumLost() { + report("!!! Quorum lost !!!"); + } + + /** + * Cluster status updatet + */ + public void statusUpdate(nClusterStatus update) { + report("Cluster status changed "); + report(update.getName() + " elected Master = " + update.getElectedMaster()); + for (int x = 0; x < update.size(); x++) { + nClusterStatusEntry entry = update.getStatus(x); + report("*******" + entry.getName() + " Online = " + entry.isOnline()); + } + report(""); + } + + /** + * Cluster state change + */ + public void stateChange(nRealmNode node, String newState) { + report("Node " + node.getName() + " changed state to " + newState); + } + + /** + * Cluster log event + */ + public void report(String source, String message) { + report("CLUSTER>> " + source + "> " + message); + } + + /** + * Update from the realm node that a cluster has been created + */ + public void update(Observable o, Object arg) { + if (arg instanceof nClusterNode) { + report("New cluster formed, name = " + ((nClusterNode) arg).getName()); + ((nClusterNode) arg).addListener(this); + } + } + + public synchronized void report(String tmp) { + Date dt = new Date(); + System.out.println(dt.toString() + " > " + tmp); + } + + private class RealmMonitor extends Thread { + + private nRealmNode myRealm; + private nChannel myMonitor; + private String myName; + private long myLastEID; + + public RealmMonitor(nRealmNode node) { + myRealm = node; + try { + myName = myRealm.getSession().getServerRealmName(); + super.setName(myName); + } catch (nSessionNotConnectedException e) { + + } + nChannelAttributes ca = new nChannelAttributes(); + try { + ca.setName("ClusterMonitor"); + myMonitor = myRealm.getSession().findChannel(ca); + } catch (Exception e) { + e.printStackTrace(); + return; + } + setDaemon(true); + start(); + } + + public long getLastEID() { + try { + myLastEID = myMonitor.getLastEID(); + } catch (Exception e) { + e.printStackTrace(); + } + return myLastEID; + } + + public nRealmNode getNode() { + return myRealm; + } + + public String getRealmName() { + return myName; + } + + public void run() { + + while (true) { + try { + Thread.sleep(60000); + } catch (InterruptedException e) { + } + nConsumeEvent ce = new nConsumeEvent("1", myName.getBytes()); + try { + myMonitor.publish(ce); + try { + Thread.sleep(2000); + } catch (InterruptedException e) { + } + } catch (Exception e) { + } + } + } + } +} diff --git a/src/main/java/com/newrelic/nri/softwareag/ums/UMSClusterMonitor.java b/src/main/java/com/newrelic/nri/softwareag/ums/UMSClusterMonitor.java new file mode 100644 index 0000000..8318ded --- /dev/null +++ b/src/main/java/com/newrelic/nri/softwareag/ums/UMSClusterMonitor.java @@ -0,0 +1,231 @@ +package com.newrelic.nri.softwareag.ums; + +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.Iterator; +import java.util.List; + +import com.newrelic.nri.softwareag.ums.metrics.AttributeMetric; +import com.newrelic.nri.softwareag.ums.metrics.GaugeMetric; +import com.newrelic.nri.softwareag.ums.metrics.Metric; +import com.pcbsys.nirvana.client.nIllegalArgumentException; +import com.pcbsys.nirvana.client.nSessionAttributes; +import com.pcbsys.nirvana.nAdminAPI.nBaseAdminException; +import com.pcbsys.nirvana.nAdminAPI.nClusterNode; +import com.pcbsys.nirvana.nAdminAPI.nClusterStatus; +import com.pcbsys.nirvana.nAdminAPI.nClusterStatusEntry; +import com.pcbsys.nirvana.nAdminAPI.nLeafNode; +import com.pcbsys.nirvana.nAdminAPI.nRealmNode; + +public class UMSClusterMonitor { + private UMServer umeServer; + private nRealmNode realmNode; + private nClusterNode clusterNode = null; + private List channels = new ArrayList<>(); + private List queues = new ArrayList<>(); + private List realms = new ArrayList<>(); + + public UMSClusterMonitor(UMServer ems) { + umeServer = ems; + } + + private void connect(UMServer server) { + if (server == null) { + Utils.reportError("UMServer instance is null"); + return; + } + + String host = server.getUMSURL(); + String username = server.getUsername(); + String password = server.getPassword(); + + try { + realmNode = new nRealmNode(new nSessionAttributes(host), username, password); + } catch (nBaseAdminException | nIllegalArgumentException e) { + Utils.reportError("Failed to connect", e); + } + } + + private void waitForRealmNodeNameSpace(nRealmNode realmNode) { + if (realmNode == null) { + Utils.reportError("RealmNode is null"); + return; + } + try { + Thread.sleep(realmNode.getUpdateInterval()); + } catch (InterruptedException e) { + Utils.reportError("Error during sleep", e); + } + } + + + public void populateMetrics(JSONMetricReporter metricReporter) { + if (umeServer == null) { + Utils.reportError("UMEServer instance is null"); + return; + } + + connect(umeServer); + + if (realms != null) { + this.getClusterStats(metricReporter); + for (nRealmNode realm : realms) { + UMSMonitor realmMonitor = new UMSMonitor(umeServer); + realmMonitor.connectRealm(realm); + realmMonitor.getChannelStats(metricReporter); + realmMonitor.getQueueStats(metricReporter); + + } + } + } + + private void addGaugeMetric(List metricList, String name, Number value) { + if (metricList == null || name == null || value == null) { + Utils.reportError("Input arguments are null"); + return; + } + + Number convertedValue = (value instanceof Long) ? new Float(value.floatValue()) : value; + metricList.add(new GaugeMetric(name, convertedValue)); + } + + protected void getClusterStats(JSONMetricReporter metricReporter) { + try { + if (realmNode == null) { + Utils.reportError("RealmNode is null"); + return; + } + + List metricList = new ArrayList<>(); + waitForRealmNodeNameSpace(realmNode); + this.clusterNode = this.realmNode.getCluster(); + metricList.clear(); + + if (this.clusterNode != null) { + String clusterName = this.clusterNode.getName().trim(); + metricList.add(new AttributeMetric("Cluster Name", clusterName)); + + Enumeration nodes = this.clusterNode.getNodes(); + + + Iterator connectionStatusIterator = this.clusterNode.getClusterConnectionStatus().iterator(); + + while (nodes.hasMoreElements()) { + nRealmNode realm = (nRealmNode) nodes.nextElement(); + realms.add(realm); + } + + while (connectionStatusIterator.hasNext()) { + Object connectionStatusObject = connectionStatusIterator.next(); + nClusterStatus clusterStatus = (nClusterStatus) connectionStatusObject; + // System.out.println(clusterStatus.getName()); + + metricList.add(new AttributeMetric("Member", clusterStatus.getName())); + // System.out.println(clusterStatus.getState()); + metricList.add(new AttributeMetric("State", clusterStatus.getState())); + metricList.add(new AttributeMetric("Master", clusterStatus.getElectedMaster())); + + nClusterStatusEntry statusEntry = clusterStatus.getStatus(clusterStatus.getName()); + if (statusEntry != null) { + // System.out.println(); + if (statusEntry.isOnline()) { + // System.out.println("online"); + metricList.add(new AttributeMetric("Status", "online")); + } else { + metricList.add(new AttributeMetric("Status", "offline")); + } + + metricList.add(new AttributeMetric("Broadcast Time", statusEntry.getBroadcastTime())); + metricList.add(new AttributeMetric("Comms Queue Size", statusEntry.getCommsQueueSize())); + metricList.add(new AttributeMetric("Queue Size", statusEntry.getQueueSize())); + metricList.add(new AttributeMetric("Response Time", statusEntry.getResponseTime())); + metricList.add(new AttributeMetric("Client Request Size", statusEntry.getClientRequestSize())); + } + metricReporter.report("Cluster Metrics", StatType.Cluster, metricList); + metricList.clear(); + metricList.add(new AttributeMetric("Cluster Name", clusterName)); + + } + } + } catch (Exception e) { + Utils.reportError("Exception occurred", e); + } + } + + protected void getChannelStats(JSONMetricReporter metricReporter) { + try { + if (realmNode == null) { + Utils.reportError("RealmNode is null"); + return; + } + + String emsServerName = realmNode.getName().trim(); + List channelInfos = channels; + List metricList = new ArrayList<>(); + + if (channelInfos != null) { + for (nLeafNode channel : channelInfos) { + metricList.clear(); + String channelName = channel.getName().trim(); + metricList.add(new AttributeMetric("UM Server", emsServerName)); + metricList.add(new AttributeMetric("Channel Name", channelName)); + addGenericMetrics(channel, metricList); + metricReporter.report("Channel Metrics", StatType.Channel, metricList); + } + } + } catch (Exception e) { + Utils.reportError("Exception occurred", e); + } + } + + protected void getQueueStats(JSONMetricReporter metricReporter) { + try { + if (realmNode == null) { + Utils.reportError("RealmNode is null"); + return; + } + + String emsServerName = realmNode.getName().trim(); + List queueInfos = queues; + List metricList = new ArrayList<>(); + + if (queueInfos != null) { + for (nLeafNode queue : queueInfos) { + metricList.clear(); + String queueName = queue.getName().trim(); + metricList.add(new AttributeMetric("UM Server", emsServerName)); + metricList.add(new AttributeMetric("Queue Name", queueName)); + addGenericMetrics(queue, metricList); + metricReporter.report("Queue Metrics", StatType.Queue, metricList); + } + } + } catch (Exception e) { + Utils.reportError("Exception occurred", e); + } + } + + + + protected void addGenericMetrics(nLeafNode node, List metricList) { + metricList.add(new AttributeMetric("AbsolutePath", node.getAbsolutePath())); + + // Events + addGaugeMetric(metricList, "Current Number Of Events", node.getCurrentNumberOfEvents()); + addGaugeMetric(metricList, "Used Space", node.getUsedSpace()); + addGaugeMetric(metricList, "Memory Usage", node.getMemoryUsage()); + addGaugeMetric(metricList, "Cache Hit Ratio", node.getCacheHitRatio()); + addGaugeMetric(metricList, "Free Percentage", node.getPercentageFreeInStore()); + + // Totals + addGaugeMetric(metricList, "Published Total", node.getTotalPublished()); + addGaugeMetric(metricList, "Consumed Total", node.getTotalConsumed()); + addGaugeMetric(metricList, "Connection Total", node.getTotalNoOfConnections()); + addGaugeMetric(metricList, "Connection Current", node.getCurrentNoOfConnections()); + + // Rates + addGaugeMetric(metricList, "Published Rate", node.getPublishRate()); + addGaugeMetric(metricList, "Consumed Rate", node.getConsumedRate()); + addGaugeMetric(metricList, "Connection Rate", node.getConnectionRate()); + addGaugeMetric(metricList, "Fanout Time (ms)", node.getFanoutTime()); + } +} diff --git a/src/main/java/com/newrelic/nri/softwareag/ums/UMSMonitor.java b/src/main/java/com/newrelic/nri/softwareag/ums/UMSMonitor.java index 5ec5bcb..d95537f 100644 --- a/src/main/java/com/newrelic/nri/softwareag/ums/UMSMonitor.java +++ b/src/main/java/com/newrelic/nri/softwareag/ums/UMSMonitor.java @@ -43,6 +43,15 @@ private void connect(UMServer m) { Utils.reportError("Failed to connect", e); } } + public void connectRealm(nRealmNode rNode) { + + realmNode = rNode; + // System.out.println(); + // System.out.println("Connected to Realm : " + realmNode.getName()); + // System.out.println(); + waitForRealmNodeNameSpace (realmNode); + scanRealmForChannelsAndQueues(realmNode.getNodes()); + } private void waitForRealmNodeNameSpace (nRealmNode realmNode) { // realmNode.waitForEntireNameSpace(); try { @@ -52,18 +61,20 @@ private void waitForRealmNodeNameSpace (nRealmNode realmNode) { } } private void scanRealmForChannelsAndQueues(@SuppressWarnings("rawtypes") final Enumeration realmNamespaceNodes) { - while (realmNamespaceNodes.hasMoreElements()) { + // System.out.println("1"); + while (realmNamespaceNodes.hasMoreElements()) { final nNode child = (nNode) realmNamespaceNodes.nextElement(); - + //System.out.println("2"); if (child instanceof nLeafNode) { final nLeafNode leafNode = (nLeafNode) child; - + //System.out.println("3"); if (leafNode.isChannel()) { channels.add(leafNode); } else if (leafNode.isQueue()) { queues.add(leafNode); } } else if (child instanceof nContainer) { + // System.out.println("4"); scanRealmForChannelsAndQueues(((nContainer) child).getNodes()); } } diff --git a/src/main/java/com/newrelic/nri/softwareag/ums/UMSMonitorFactory.java b/src/main/java/com/newrelic/nri/softwareag/ums/UMSMonitorFactory.java index f916e0d..6410e42 100644 --- a/src/main/java/com/newrelic/nri/softwareag/ums/UMSMonitorFactory.java +++ b/src/main/java/com/newrelic/nri/softwareag/ums/UMSMonitorFactory.java @@ -7,7 +7,8 @@ public class UMSMonitorFactory { private static final Number DEFAULT_PORT = 9000; private static String MANGLED_PREFIX = "-UMS-"; - public UMSMonitor createAgent(Map properties) throws Exception { + public Object createAgent(Map properties) throws Exception { + String name = (String) properties.get("name"); String host = (String) properties.get("host"); Number port = (Number) properties.get("port"); @@ -33,10 +34,21 @@ public UMSMonitor createAgent(Map properties) throws Exception { encryptPassword = false; } + Boolean isCluster = (Boolean) properties.get("isCluster"); + if (null == isCluster) + { + isCluster = true; // default is true + } + + Object agent = null; UMServer ems = new UMServer(name, host, port.intValue(), username, password, aeskey, encryptPassword); - UMSMonitor agent = new UMSMonitor(ems); + if(isCluster) { + agent = new UMSClusterMonitor(ems); + } + else + agent = new UMSMonitor(ems); return agent; } diff --git a/src/main/java/com/newrelic/nri/softwareag/ums/UMServer.java b/src/main/java/com/newrelic/nri/softwareag/ums/UMServer.java index 7ebf9a4..3501f2f 100644 --- a/src/main/java/com/newrelic/nri/softwareag/ums/UMServer.java +++ b/src/main/java/com/newrelic/nri/softwareag/ums/UMServer.java @@ -1,5 +1,7 @@ package com.newrelic.nri.softwareag.ums; +import com.pcbsys.nirvana.nAdminAPI.nClusterNode; + public class UMServer { private String host; private int port = 9000; // default port @@ -9,6 +11,7 @@ public class UMServer { private String password; private String aeskey; private boolean encpwd=false; + public UMServer(String name, String host, int port, String username, String password, String aeskey, boolean encpwd) { this.name = name; diff --git a/src/main/java/com/newrelic/nri/softwareag/ums/Utils.java b/src/main/java/com/newrelic/nri/softwareag/ums/Utils.java index 5a4c73d..e1a7fbd 100644 --- a/src/main/java/com/newrelic/nri/softwareag/ums/Utils.java +++ b/src/main/java/com/newrelic/nri/softwareag/ums/Utils.java @@ -7,7 +7,7 @@ import org.json.simple.JSONObject; public class Utils { - private static final String NAME = "Tibco_EMS"; + private static final String NAME = "SoftwareAG_UMS"; JSONArray dataArray = new JSONArray(); private static final String PROTOCOL_VERSION = Integer.toString(2); @@ -23,7 +23,7 @@ public static void reportError(String msg, Throwable t) { JSONArray dataArray = new JSONArray(); JSONObject json2 = new JSONObject(); JSONObject entity = new JSONObject(); - entity.put("name", "TibcoEMSError"); + entity.put("name", "SoftwareAGUMSError"); entity.put("type", "Error"); json2.put("entity", entity);