changeset 465:5401dadf33bb

SNMP logger
author Devel 3
date Wed, 02 Aug 2017 16:15:14 +0200
parents fa4e311fdf65
children d76b45adf852
files stress-tester-reporter/pom.xml stress-tester-reporter/src/main/java/com/passus/st/reporter/SnmpLogger.java stress-tester-reporter/src/main/java/com/passus/st/reporter/server/ReporterImpl.java stress-tester-reporter/src/main/java/com/passus/st/reporter/server/ServerMain.java
diffstat 4 files changed, 269 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/stress-tester-reporter/pom.xml	Wed Aug 02 14:51:49 2017 +0200
+++ b/stress-tester-reporter/pom.xml	Wed Aug 02 16:15:14 2017 +0200
@@ -48,6 +48,23 @@
             <version>6.8.1</version>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>org.snmp4j</groupId>
+            <artifactId>snmp4j</artifactId>
+            <version>2.5.0</version>
+        </dependency>
+        
+        <dependency>
+            <groupId>commons-cli</groupId>
+            <artifactId>commons-cli</artifactId>
+            <version>1.3.1</version>
+        </dependency>
+        <dependency>
+            <groupId>com.passus.st</groupId>
+            <artifactId>stress-tester</artifactId>
+            <version>1.0-SNAPSHOT</version>
+            <type>jar</type>
+        </dependency>
     </dependencies>
     
     <build>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stress-tester-reporter/src/main/java/com/passus/st/reporter/SnmpLogger.java	Wed Aug 02 16:15:14 2017 +0200
@@ -0,0 +1,177 @@
+package com.passus.st.reporter;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
+
+import org.snmp4j.CommunityTarget;
+import org.snmp4j.PDU;
+import org.snmp4j.Snmp;
+import org.snmp4j.Target;
+import org.snmp4j.TransportMapping;
+import org.snmp4j.event.ResponseEvent;
+import org.snmp4j.mp.SnmpConstants;
+import org.snmp4j.smi.Address;
+import org.snmp4j.smi.GenericAddress;
+import org.snmp4j.smi.OID;
+import org.snmp4j.smi.OctetString;
+import org.snmp4j.smi.VariableBinding;
+import org.snmp4j.transport.DefaultUdpTransportMapping;
+
+public class SnmpLogger implements Runnable {
+    private OID oid_cpuLoad1m = new OID(".1.3.6.1.4.1.2021.10.1.3.1");
+    private OID oid_cpuLoad5m = new OID(".1.3.6.1.4.1.2021.10.1.3.2");
+    private OID oid_cpuLoad15m = new OID(".1.3.6.1.4.1.2021.10.1.3.3");
+    private OID oid_ramFree = new OID(".1.3.6.1.4.1.2021.4.6.0");
+    private OID oid_ramTotal = new OID(".1.3.6.1.4.1.2021.4.5.0");
+    private OID oid_swapFree = new OID(".1.3.6.1.4.1.2021.4.4.0");
+    private OID oid_swapTotal = new OID(".1.3.6.1.4.1.2021.4.3.0");
+    
+    private final ScheduledExecutorService scheduler = 
+       Executors.newScheduledThreadPool(1);
+    
+    private Snmp snmp = null;
+    private String address = null;
+    private String community = "passus";
+    private PrintWriter file = null;
+    private boolean initialized = false;
+    private StringBuilder builder;
+    private ScheduledFuture<?> scheduleHandle;
+    
+    public boolean isInitialized() {
+        return initialized;
+    }
+
+    public void setInitialized(boolean initialized) {
+        this.initialized = initialized;
+    }
+    
+    /**
+     * Constructor
+     *
+     * @param add must be quasi url, (ex. udp:172.16.60.101/161)
+     * @param comm name of the SNMP community
+     */
+    public SnmpLogger(final String add, final String comm, final int period) {
+        
+        address = add;
+        community = comm;
+        try {
+            file = new PrintWriter("snmp.csv", "UTF-8");
+            this.initialize();
+            this.initialized = true;
+            this.builder = new StringBuilder(200);
+            scheduleHandle = scheduler.scheduleAtFixedRate(this, 1, period, TimeUnit.SECONDS);
+        } catch (IOException ex) {
+            System.err.println(ex);
+        }
+        
+    }
+
+    public void run(){
+        try {
+            builder = new StringBuilder(200);
+            builder.append(System.currentTimeMillis());
+            builder.append(";");
+            String cpuLoad1m = this.getAsString(oid_cpuLoad1m);
+            String cpuLoad5m = this.getAsString(oid_cpuLoad5m);
+            String cpuLoad15m = this.getAsString(oid_cpuLoad15m);
+            String ramFree = this.getAsString(oid_ramFree);
+            String swapFree = this.getAsString(oid_swapFree);
+            String ramTotal = this.getAsString(oid_ramTotal);
+            String swapTotal = this.getAsString(oid_swapTotal);
+            builder.append(cpuLoad1m);
+            builder.append(";");
+            builder.append(cpuLoad5m);
+            builder.append(";");
+            builder.append(cpuLoad15m);
+            builder.append(";");
+            builder.append(Integer.parseInt(ramTotal) - Integer.parseInt(ramFree));
+            builder.append(";");
+            builder.append(Integer.parseInt(swapTotal) - Integer.parseInt(swapFree));
+            builder.append("\n");
+            
+            file.write(builder.toString());
+            file.flush();
+        } catch (IOException ex) {
+            System.err.println(ex);
+        }
+        
+    }
+
+    /**
+     * Start the Snmp session.
+     *
+     * @throws IOException
+     */
+    private void initialize() throws IOException {
+        TransportMapping transport = new DefaultUdpTransportMapping();
+        snmp = new Snmp(transport);
+        transport.listen();
+    }
+    
+    public void close() {
+        try {
+            scheduleHandle.cancel(true);
+        
+            snmp.close();
+            file.close();
+        } catch (IOException ex) {
+            System.err.println(ex);
+        }
+    } 
+
+    /**
+     * Method which takes a single OID and returns the response from the agent
+     * as a String.
+     *
+     * @param oid
+     * @return
+     * @throws IOException
+     */
+    public String getAsString(OID oid) throws IOException {
+        ResponseEvent event = get(new OID[]{oid});
+        return event.getResponse().get(0).getVariable().toString();
+    }
+
+    /**
+     * This method is capable of handling multiple OIDs
+     *
+     * @param oids
+     * @return
+     * @throws IOException
+     */
+    public ResponseEvent get(OID oids[]) throws IOException {
+        PDU pdu = new PDU();
+        for (OID oid : oids) {
+            pdu.add(new VariableBinding(oid));
+        }
+        pdu.setType(PDU.GET);
+        ResponseEvent event = snmp.send(pdu, getTarget(), null);
+        if (event != null) {
+            return event;
+        }
+        throw new RuntimeException("GET timed out");
+    }
+
+    /**
+     * This method returns a Target, which contains information about where the
+     * data should be fetched and how.
+     *
+     * @return
+     */
+    private Target getTarget() {
+        Address targetAddress = GenericAddress.parse(address);
+        CommunityTarget target = new CommunityTarget();
+        target.setCommunity(new OctetString(community));
+        target.setAddress(targetAddress);
+        target.setRetries(2);
+        target.setTimeout(1500);
+        target.setVersion(SnmpConstants.version2c);
+        return target;
+    }
+
+}
--- a/stress-tester-reporter/src/main/java/com/passus/st/reporter/server/ReporterImpl.java	Wed Aug 02 14:51:49 2017 +0200
+++ b/stress-tester-reporter/src/main/java/com/passus/st/reporter/server/ReporterImpl.java	Wed Aug 02 16:15:14 2017 +0200
@@ -82,7 +82,7 @@
             addValue(builder, getMapValue(misc, "username"));
             reqFile.println(builder.toString());
             reqFile.flush();
-            System.out.println(builder.toString());
+//            System.out.println(builder.toString());
         }
         if (code.equalsIgnoreCase("httpResponse")) {
             addValue(builder, fields.get(new Utf8("reqId")));
@@ -100,7 +100,7 @@
             addValue(builder, fields.get(new Utf8("messageContentSize")));
             respFile.println(builder.toString());
             respFile.flush();
-            System.out.println(builder.toString());
+//            System.out.println(builder.toString());
         }
 
         if (verbose) {
@@ -127,8 +127,24 @@
             Map<CharSequence, Object> emitterFields = emitterMetric.getFields();
             addValue(builder, emitterFields.get(new Utf8("receivedBytes")));
             addValue(builder, emitterFields.get(new Utf8("sentBytes")));
+            addValue(builder, emitterFields.get(new Utf8("establishedConnections")));
+            addValue(builder, emitterFields.get(new Utf8("closedConnections")));
+            addValue(builder, emitterFields.get(new Utf8("bindErrors")));
+            
+        } else {
+            builder.append(";;;;;");
         }
-
+        
+        emitterMetric = findMetric(collection, "pcapSource");
+        if (emitterMetric != null) {
+            Map<CharSequence, Object> emitterFields = emitterMetric.getFields();
+            addValue(builder, emitterFields.get(new Utf8("frames")));
+            addValue(builder, emitterFields.get(new Utf8("tcpPackets")));
+        } else {
+            builder.append(";;");
+        }
+        
+        
         emitterFile.println(builder.toString());
         emitterFile.flush();
 
--- a/stress-tester-reporter/src/main/java/com/passus/st/reporter/server/ServerMain.java	Wed Aug 02 14:51:49 2017 +0200
+++ b/stress-tester-reporter/src/main/java/com/passus/st/reporter/server/ServerMain.java	Wed Aug 02 16:15:14 2017 +0200
@@ -1,5 +1,6 @@
 package com.passus.st.reporter.server;
 
+import com.passus.st.reporter.SnmpLogger;
 import com.passus.st.reporter.protocol.Reporter;
 import java.io.IOException;
 import java.net.InetSocketAddress;
@@ -7,6 +8,12 @@
 import org.apache.avro.ipc.Responder;
 import org.apache.avro.ipc.Server;
 import org.apache.avro.ipc.specific.SpecificResponder;
+import org.apache.commons.cli.Options;
+import static com.passus.st.utils.CliUtils.option;
+import org.apache.commons.cli.DefaultParser;
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.HelpFormatter;
+import org.apache.commons.cli.ParseException;
 
 /**
  *
@@ -15,18 +22,66 @@
 public class ServerMain {
 
     static final int PORT = 11111;
+    static SnmpLogger snmp;
+    
+    static void printHelp(Options options) {
+        HelpFormatter formatter = new HelpFormatter();
+        formatter.printHelp("[options]", "description", options, "");
+    }
+
+    static void printError(String msg) {
+        System.err.print(msg);
+        System.exit(1);
+    }
 
     public static void main(String[] args) throws IOException {
+
+        final Options options = new Options();
+
+        options.addOption(option("s", "snmp").desc("Collect SNMP metrics.")
+                .hasArg().argName("snmpAddr")
+                .build()
+        );
+        options.addOption(option("co", "snmpCommunity").desc("SNMP Community.")
+                .hasArg().argName("snmpCommunity")
+                .build()
+        );
+        options.addOption(option("p", "snmpPeriod").desc("Period in seconds of consequent SNMP readings.")
+                .hasArg().argName("snmpPeriod")
+                .build()
+        );
+
+        try {
+            CommandLine cl = new DefaultParser().parse(options, args);
+            if (cl.hasOption("s")) {
+                // SNMP listener is enabled
+                String snmpAddr = cl.getOptionValue("s");
+                String snmpCommunity = cl.hasOption("co") ? cl.getOptionValue("co") : "passus";
+                int snmpPeriod = cl.hasOption("p") ? Integer.parseUnsignedInt(cl.getOptionValue("p")) : 5;
+                snmp = new SnmpLogger(snmpAddr, snmpCommunity, snmpPeriod);
+            } else if (cl.hasOption("co") || cl.hasOption("p")) {
+                // Community option without SNMP option specified
+                printError("Options <snmpCommunity> and <snmpPeriod> require to specify SNMP Address.");
+                return;
+            }
+        } catch (ParseException ex) {
+            System.out.println(ex.getMessage());
+            printHelp(options);
+            return;
+        }
+
         InetSocketAddress serverAddress = new InetSocketAddress(PORT);
         ReporterImpl reporter = new ReporterImpl();
         reporter.setVerbose(false);
         Responder responder = new SpecificResponder(Reporter.class, reporter);
         Server server = new NettyServer(responder, serverAddress);
         System.out.println("Server started.");
-
         Runnable shutdown = () -> {
             server.close();
             reporter.close();
+            if (snmp != null) {
+                snmp.close();
+            }
             System.out.println("Server closed.");
         };
         Runtime.getRuntime().addShutdownHook(new Thread(shutdown));