pmonframe logo
  Abstract   First Steps   XML Network Interface   Java Doc   Real World Example   FAQ   Download   Contact  

Real World Example

At the bottom of this web page is the source code of this "real world" example. The example consists of two stand-alone programs, both of which are started from the command line: Because in this case the PmonframeSigarHttpServer provides data for 4 measurement collections, the PmonframeJFreeChartHttpClient will generate 4 images. The pmonframe client uses the XML command getDataCollectionDirectory to discover the measurement collections. The filenames of the images are derived by using the identifier of the measurement collections; that is CPU.png, MEMORY.png, TCP-EST.png and TCP-TIMEWAIT.png:
 
 
To run this example proceed as follows:
  1. Download the SIGAR libraries: sigar.jar and the native sigar library for your operating system.
  2. Download the JFreeChart libraries: jfreechart-1.0.13.jar and jcommon-1.0.16.jar (or newer versions)
  3. Download the pmonframe library: pmonframe-0.91.jar (see download section)
  4. Copy and paste the source code below for the two Java programs into your development environment, or into a text editor, and save the source code as two files named PmonframeSigarHttpServer.java and PmonframeJFreeChartHttpClient.java respectively.
  5. Set your CLASSPATH, and then compile the two source files (Java 1.5 or Java 1.6 is required)
First, start the pmonframe server program, and let it collect the data for one or more minutes. Then repeatedly run the pmonframe client program to get actual charts. To easily display the images, you can also create a HTML file inside the directory where the images are stored:
<html>
<body>
<img src="CPU.png">
<img src="MEMORY.png">
<img src="TCP-EST.png">
<img src="TCP-TIMEWAIT.png">
</body>
</html>
Name this HTML code file displayCharts.html, and open it with a web browser. Now when you start the PmonframeJFreeChartHttpClient once more, you can simply click on the reload icon inside your web browser to see the new images
 
Note: Please note that we cannot provide support for questions related to SIGAR or JFreeChart. You must also be aware of, and comply with, the relevant license terms and conditions when using this real world example. pmonframe is licensed under the Apache License (version 2). SIGAR is licensed under the GPL license (but contains a "FLOSS License Exception" for Apache licenses). JFreeChart is licensed under the LGPL license. Note also that this real world example is not part of the source code of pmonframe, and also not part of the compiled code of pmonframe.
 

PmonframeSigarHttpServer.java  (requires pmonframe-0.91.jar, sigar.jar and the native sigar library for your operating system)
import org.pmonframe.server.HttpServer;
import org.pmonframe.server.ServerLog;
import org.pmonframe.data.*;

import org.hyperic.sigar.Sigar;
import org.hyperic.sigar.CpuPerc;
import org.hyperic.sigar.Mem;
import org.hyperic.sigar.NetStat;


/**
 * HTTP pmonframe server program which collects from the operating system the CPU Usage,
 * the Memory Usage, the number of Established TCP Connections and the number of TCP
 * Connections in Time Wait State.
 */
public class PmonframeSigarHttpServer extends HttpServer
// ======================================================================================
{

  public PmonframeSigarHttpServer(String serverAbbreviation)
  // --- constructor ------------------------------------------------------------------
  {
    super(serverAbbreviation);
  }


  public PmonframeSigarHttpServer(String serverAbbreviation, int serverPort)
  // --- constructor ------------------------------------------------------------------
  {
    super(serverAbbreviation, serverPort);
  }


  /**
   * Server main program.
   */
  public static void main(String[] args)
  // ----------------------------------------------------------------------------------
  {
    int serverPort = 39002;
    int logLevel = ServerLog.STANDARD;

    // check for optional command line arguments -port <tcp port number> and -loglevel <nolog | standard | debug>
    for (int x = 0; x < args.length; x++)
    {
      if (args[x].equalsIgnoreCase("-port") && (x < (args.length - 1)))
        serverPort = Integer.valueOf(args[x + 1]).intValue();

      if (args[x].equalsIgnoreCase("-loglevel") && (x < (args.length - 1)))
      {
        if (args[x + 1].equalsIgnoreCase("nolog"))
          logLevel = ServerLog.NOLOG;

        if (args[x + 1].equalsIgnoreCase("debug"))
          logLevel = ServerLog.DEBUG;
      }
    }

    // set log level
    ServerLog.setLogLevel(logLevel);

    try
    {
      Sigar sigar = new Sigar();

      // start the server
      // ----------------
      PmonframeSigarHttpServer server = new PmonframeSigarHttpServer("EXSRV", serverPort);
      // server.setAddCRLFtoXMLResponses();  // you should not use this for real servers
      server.start();

      // define collected data
      // ---------------------
      MeasuringDataTree dataTree = server.getMeasuringDataTree();

      // cpu usage in %
      MeasurementCollection cpuCollection = dataTree.createMeasurementCollection("CPU", "CPU Usage in Percent", "Percent", MeasurementCollection.DATA_TYPE_PERCENT_VALUE);
      cpuCollection.setSubtitle("Calculated overall CPUs and Cores");

      // memory usage in %
      MeasurementCollection memoryCollection = dataTree.createMeasurementCollection("MEMORY", "Memory Usage in Percent", "Percent", MeasurementCollection.DATA_TYPE_PERCENT_VALUE);
        memoryCollection.setSubtitle("Volatile Memory (RAM)");

      // established TCP connections
      MeasurementCollection establishedTcpCollection = dataTree.createMeasurementCollection("TCP-EST", "Established TCP Connections", "Number of Connections", MeasurementCollection.DATA_TYPE_INTEGER_VALUE);
      establishedTcpCollection.setSubtitle("Currently Open Connections");

      // TCP connections in time wait state
      MeasurementCollection timeWaitTcpCollection = dataTree.createMeasurementCollection("TCP-TIMEWAIT", "TCP Connections in Time Wait State", "Number of Connections", MeasurementCollection.DATA_TYPE_INTEGER_VALUE);
      timeWaitTcpCollection.setSubtitle("Connections Waiting to be Closed by the OS");

      // mark server as operable
      server.markAsOperable(true);

      // collect data in a infinite loop
      // -------------------------------
      while (true)
      {
        try
        {
          // cpu usage in %
          CpuPerc cpuPerc = sigar.getCpuPerc();
          PercentValue cpuValue = new PercentValue((float)(cpuPerc.getCombined() * 100.0d));
          cpuCollection.addValue(cpuValue);

          // memory usage in %
          Mem mem = sigar.getMem();
          PercentValue memoryValue = new PercentValue((float)mem.getUsedPercent());
          memoryCollection.addValue(memoryValue);

          // established TCP connections
          NetStat netstat = sigar.getNetStat();
          IntegerValue tcpEstConnections = new IntegerValue(netstat.getTcpEstablished());
          establishedTcpCollection.addValue(tcpEstConnections);

          // TCP connections in time wait state
          IntegerValue tcpTimewaitConnections = new IntegerValue(netstat.getTcpTimeWait());
          timeWaitTcpCollection.addValue(tcpTimewaitConnections);
        }
        catch (Exception ex)
        {
          ServerLog.log(ex);
        }

        // wait 3 seconds
        sleep(3000);
      }
    }
    catch (Exception e)
    {
      ServerLog.log(e);
      System.exit(1);
    }
  }
}

PmonframeJFreeChartHttpClient.java  (requires pmonframe-0.91.jar, and the two JFreeChart libraries jfreechart-1.0.13.jar and jcommon-1.0.16.jar)
import java.io.*;
import java.awt.Font;
import java.text.DecimalFormat;
import java.util.HashMap;
import java.util.StringTokenizer;
import java.util.TimeZone;
import java.util.Vector;

import org.pmonframe.client.HttpConnection;
import org.pmonframe.client.XMLClientRequest;
import org.pmonframe.client.XMLDataCollectionDirectoryParser;
import org.pmonframe.client.XMLDataCollectionsGenericValueParser;
import org.pmonframe.client.MeasurementCollectionMetadata;
import org.pmonframe.client.DataCollectionGenericValueData;
import org.pmonframe.client.GenericValueData;

import org.w3c.dom.Document;

import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.title.TextTitle;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.axis.DateAxis;
import org.jfree.data.time.TimeTableXYDataset;
import org.jfree.data.time.FixedMillisecond;
import org.jfree.ui.RectangleEdge;
import org.jfree.ui.VerticalAlignment;


/**
 * Generic program capable to request measuring data from any pmonframe server and
 * to generate from them charts which are stored on disk in PNG format.
 */
public class PmonframeJFreeChartHttpClient
// ======================================================================================
{

  public static void main(String[] args)
  // ----------------------------------------------------------------------------------
  {
    String serverHost = "127.0.0.1";
    int serverPort = 39002;
    TimeZone alternativeTimeZone = null;


    // check for optional command line arguments -server <name or IP>, -port <number> and -tz <display in time zone>
    for (int x = 0; x < args.length; x++)
    {
      if (args[x].equalsIgnoreCase("-server") && (x < (args.length - 1)))
        serverHost = args[x + 1];

      if (args[x].equalsIgnoreCase("-port") && (x < (args.length - 1)))
        serverPort = Integer.valueOf(args[x + 1]).intValue();

      if (args[x].equalsIgnoreCase("-tz") && (x < (args.length - 1)))
      {
        String userSelectedTimeZoneId = args[x + 1];

        String[] timeZoneId = TimeZone.getAvailableIDs();
        for (int y = 0; y < timeZoneId.length; y++)
        {
          if (userSelectedTimeZoneId.equalsIgnoreCase(timeZoneId[y]))
          {
            alternativeTimeZone = TimeZone.getTimeZone(timeZoneId[y]);
            break;
          }
        }
        if (alternativeTimeZone == null)
        {
          System.out.println("Input error: invalid value for -tz argument \"" + userSelectedTimeZoneId + "\". Supported time zones are:");
          for (int y = 0; y < timeZoneId.length; y++)
            System.out.println("\"" + timeZoneId[y] + "\"");
          System.exit(1);
        }
      }
    }

    try
    {
      BufferedReader userInput = new BufferedReader(new InputStreamReader(System.in));

      // display list of all available measurement collections on <host>:<port> and put them into a hash map
      // ---------------------------------------------------------------------------------------------------
      HashMap<String,MeasurementCollectionMetadata> collectionDataMap = new HashMap<String,MeasurementCollectionMetadata>();

      // get data from pmonframe server
      Document doc = HttpConnection.doRequestToServer(serverHost, serverPort, XMLClientRequest.getDataCollectionDirectory(), false);
      XMLDataCollectionDirectoryParser directoryParser = new XMLDataCollectionDirectoryParser(doc);
      MeasurementCollectionMetadata[] measurementCollections = directoryParser.getMeasurementCollectionsMetadata();

      // display list of all available measurement collections of pmonframe server
      System.out.println("List of All Available Measurement Collections on " + serverHost + ":" + serverPort);
      for (int x = 0; x < measurementCollections.length; x++)
      {
        String identifierString = measurementCollections[x].getIdentifier() + "                    ";
        identifierString = identifierString.substring(0, 20);
        System.out.println("identifier = " + identifierString + " (" + measurementCollections[x].getTitle() + ")");

        // put data of measurement collection also into a hash map
        collectionDataMap.put(measurementCollections[x].getIdentifier(), measurementCollections[x]);
      }

      // read user input to select measurement collections by pmonframe identifier
      // -------------------------------------------------------------------------
      System.out.print("Enter one or more Collection Identifier, seperated by comma (Default = all): ");
      Vector<String> v = new Vector<String>();
      StringTokenizer strtok = new StringTokenizer(userInput.readLine(), ",");
      while (strtok.hasMoreTokens())
      {
        String token = strtok.nextToken().trim();
        if (token.length() > 0)
        {
          if (collectionDataMap.containsKey(token))
            v.addElement(token);
          else
            throw new RuntimeException("input error: invalid identifier \"" + token + "\"");
        }
      }
      if (v.size() == 0)  // default = all measurement collections
      {
        for (int x = 0; x < measurementCollections.length; x++)
          v.addElement(measurementCollections[x].getIdentifier());
      }
      String[] monitorCollectionIdentifier = new String[v.size()];
      monitorCollectionIdentifier = v.toArray(monitorCollectionIdentifier);    // selected measurement collections


      // read user input to get time period of the charts
      // ------------------------------------------------
      System.out.print("Enter Time Period in Minutes (Default = 5): ");
      int timePeriodMinutes = 5;
      String timePeriodInput = userInput.readLine();
      if (timePeriodInput.trim().length() > 0)
        timePeriodMinutes = Integer.valueOf(timePeriodInput).intValue();


      // get the data of all measurement collections with one request
      // ------------------------------------------------------------
      doc = HttpConnection.doRequestToServer(serverHost, serverPort, XMLClientRequest.getLatestValuesSinceSeconds(monitorCollectionIdentifier, timePeriodMinutes * 60), false);
      XMLDataCollectionsGenericValueParser genericValueParser = new XMLDataCollectionsGenericValueParser(doc);
      DataCollectionGenericValueData[] dataCollectionsData = genericValueParser.getDataCollectionsGenericValues();


      // create the charts and write chart images to disk
      // --------------------------------------------------------------------------
      for (int i = 0; i < dataCollectionsData.length; i++)
      {
        GenericValueData[] valueData = dataCollectionsData[i].getValueData();

        // restore pmonframe measurement collection from hash map
        MeasurementCollectionMetadata measurementCollection = collectionDataMap.get(dataCollectionsData[i].getIdentifier());

        // create dataset for JFreeChart
        TimeTableXYDataset dataset = new TimeTableXYDataset();
        long oldestTimestamp = -1;
        long latestTimestamp = -1;
        for (int x = 0; x < valueData.length; x++)
        {
          Double d = Double.valueOf(valueData[x].getValue()).doubleValue();
          FixedMillisecond fm = new FixedMillisecond(valueData[x].getTimestamp());
          dataset.add(fm, d, measurementCollection.getIdentifier());

          if (x == 0)
            oldestTimestamp = valueData[x].getTimestamp();
          if (x == (valueData.length - 1))
            latestTimestamp = valueData[x].getTimestamp();
        }
        String timePeriodUnit = "Minute";
        if ((oldestTimestamp != -1) && (oldestTimestamp != latestTimestamp))
        {
          timePeriodMinutes = (int) ((latestTimestamp - oldestTimestamp) / 60000l) + 1;
          if (timePeriodMinutes > 1)
            timePeriodUnit = "Minutes";
        }

        // create JFreeChart image
        JFreeChart chart = ChartFactory.createTimeSeriesChart(measurementCollection.getTitle(), "Time Period: Last " + timePeriodMinutes + " " + timePeriodUnit, measurementCollection.getYAxisLabel(), dataset, false, false, false);
        chart.setTitle(new TextTitle(measurementCollection.getTitle(), new java.awt.Font("SansSerif", Font.BOLD, 20)));  // replace font of title
        if (measurementCollection.getSubtitle().trim().length() > 0)
        {
          // add subtitle to JFreeChart image
          TextTitle subtitle = new TextTitle(measurementCollection.getSubtitle());
          subtitle.setFont(new Font("SansSerif", Font.BOLD, 14));
          subtitle.setPosition(RectangleEdge.TOP);
          subtitle.setVerticalAlignment(VerticalAlignment.BOTTOM);
          chart.addSubtitle(subtitle);
        }

        // format x-axis and y-axis of JFreeChart image
        XYPlot plot = chart.getXYPlot();
        NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis();
        if (alternativeTimeZone != null)
        {
          DateAxis dateAxis = (DateAxis) plot.getDomainAxis();
          dateAxis.setTimeZone(alternativeTimeZone);
        }

        if (measurementCollection.getDataType().equalsIgnoreCase("percent"))
        {
          DecimalFormat format = new DecimalFormat("###0.0");
          rangeAxis.setNumberFormatOverride(format);

          rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
          rangeAxis.setAutoRangeIncludesZero(true);
          rangeAxis.setRangeWithMargins(0.0, 100.0);
        }

        if (measurementCollection.getDataType().equalsIgnoreCase("integer"))
        {
          DecimalFormat format = new DecimalFormat("##########0");
          rangeAxis.setNumberFormatOverride(format);

          rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
          rangeAxis.setAutoRangeIncludesZero(true);
        }

        // write JFreeChart image to disc as PNG
        String imageFileName = dataCollectionsData[i].getIdentifier() + ".png";
        FileOutputStream fout = new FileOutputStream(imageFileName);
        ChartUtilities.writeChartAsPNG(fout, chart, 400, 240);
        fout.close();
        System.out.println("Image created on disk: " + imageFileName);
      }
    }
    catch (Exception e)
    {
      e.printStackTrace();
    }
  }
}

Unless required by applicable law or agreed to in writing, this web page, inclusive the "on this web page shown program code", is published on an "as is" basis, without warranties or conditions of any kind, either express or implied.