JMeasurement is a free and simple java api for monitoring user defined aspects of the runtime of java production code. It was build with simple usage in mind. JMeasurement can help you to show in an running application, how long some defined parts of your application are running, and how often they've been called.
If you work with interfaces, you can automatically monitor a complete interface with the MeasureFactory#registerInterface() methode. Now every methode of every interface will be monitored. The names of the measure points are likley the name of the class implementing the interface with a # and the methode name.

Usage

The simplst form of using JMeasurement is this one:
...
        Monitor monitor = MeasureFactory.start("myMeasurePoint");
        ...<do something>
        monitor.stop();
        System.out.println(MeasureFactory.asString());
...
In this code we will measure only one point with the name "myMeasurePoint". The result will be shown as text in the console.

A more sophiticated example is shown below (from MeasureFactoryTest.java):
...
        Monitor monitor1;
        MeasurePoint point;
        MeasureFactory.setApplicationName("testFactory");
        MeasureFactory.setPriority(5);
        for (int i = 0; i < 10; i++) {
            point = MeasureFactory.getMeasurePoint(BASEPOINT + "."
                    + Integer.toString(i));
            point.setPriority(i);
            monitor1 = MeasureFactory.start(point.getName());
            Thread.sleep(i * 10);
            monitor1.stop();
        }

        System.out.println(MeasureFactory.getReport(new CSVDataRenderer()));
...

First we define a monitor and a measure point. Then for our Renderer we set the application name (used for the title in the HTML renderer). Then we set the priority of the factory to 5. With this only points with priority >= 5 will be measured. All other points will deliver a NullMonitor which does nothing.
Then we request a measure point, set the priority of this point to a value, get a monitor and wait.
Then we stop the monitor.
After that we let us generate an CSV report for the console output.
As we see this output will only show measurepoints with the priority >= 5. All other points are not shown. Set the priority of the factory before getting a monitor will lead in a filter for the measurment, only point with a higher will be monitored.

You can also use the priority to filter the output. In this case you must set the priority after all data will be measured before you call getReport().

Exception handling

Sometimes your code to measure will throw an exception. In this case, to avoid dead monitors, you can do something like this:
...
        Monitor monitor = MeasureFactory.start("myMeasurePoint");
        try {
          ...<do something>
        } catch(Exception e) {
          <your exception handling>
        } finally {
          monitor.stop();
        }
        System.out.println(MeasureFactory.asString());
...
In this example the monitor is always stopped, but if you don't want to measure the exception handling and you want to report the exception, you can do this:
...
        Monitor monitor = MeasureFactory.start("myMeasurePoint");
        try {
          ...<do something>
          monitor.stop();
        } catch(Exception e) {
          monitor.setException(e.toString());
          <your exception handling>
        }
        System.out.println(MeasureFactory.asString());
...
In tis example only the exception text will be recorded. To record a full stacktrace you can use this code:
...
  String stackTrace = StringFormat.getStackTrace(e.getCause());
...

Monitor interfaces

To monitor a interface you simply have to Instancing your class, the register this class in the measure factory. The result of the registering will be a proxy object with all methodes that are definied in the interfaces of this class.
Here is a simple example, (you can see the full example in the test cases of this package)
using the interface : ITestProxy
public interface ITestProxy {
    String echo(String line);

    void echoNow(String line);

    void exceptionNow() throws ProxyException;

    String iTestMethode(String line);
}
using the class : CTestProxy
public class CTestProxy implements ITestProxy {

... your code here ...
    public String echo(String line) {
... your code here ...
    }

    public void echoNow(String linie) {
... your code here ...
    }

    public void exceptionNow() throws ProxyException {
... your code here ...
    }

    public String iTestMethode(String line) {
... your code here ...
    }
}
Now to monitor the interface of a CProxyClass, do it like this:
...
	ITestProxy testProxy = (ITestProxy) MeasureFactory.registerInterface(new CTestProxy(), true, true, null);
... calling some methodes of the Interface ...
	String line = testProxy.echo("echo: This is my line.");
...
In the report you will find automatically generated MeasurePoints for every method you have called, like this:

JMeasurement HTML Report


pointName priority accessCount averageMSec totalMSec minMSec maxMSec active maxActive deathCount lastActivation exceptionCount exceptionList userData
de.mcs.jmeasurement.test.proxy.CTestProxy#echo 0 2 505 1011 501 510 0 1 0 28.07.06 15:05 0    
de.mcs.jmeasurement.test.proxy.CTestProxy#echoNow 0 2 200 401 200 201 0 1 0 28.07.06 15:05 0    
de.mcs.jmeasurement.test.proxy.CTestProxy#exceptionNow 0 2 270 541 250 291 0 1 0 28.07.06 15:05 2 View  

As you see, Exceptions will be automatically stored in the measure point, if you set the flag storeExceptions in the MeasureFactory#registerInterface() to true. (Click on the View link in the column exceptionList)

Persisting data

In the factory there is the possibility to persist and load all measured data.
{@link de.mcs.jmeasurement.MeasureFactory#saveToXMLStream(OutputStream)}
{@link de.mcs.jmeasurement.MeasureFactory#loadFromXMLStream(InputStream,boolean)}
For convinience there are to methode to directly load and save from/to files. The persisting data will be stored and retrieved as XML.

Snapshots

Snapshots are used to freeze the current measuredata at a defined point. Some time later you can report them
To take a snapshot simply code:
...
        MeasureFactory.takeSnapshot("name of this snapshot");
...
You can also render only one snapshot or remove it. Snapshots are persistent, so the loading will restore privious saved snapshots.

Configuration

Now you can configure the JMeasurement system with a simple configuration file. There are 2 methods in the MeasurementFactory to do so.
configure() and configure(File).
The first one will configure the system with a file in the classpath. This could be a standard property file called jmconfig.properties.
The second will load the given file as a properrty file.
Here is a short example of a property file:
OPTION_BACKGROUND_TIME=10000
OPTION_ENABLE_AUTOSNAPSHOT=true
OPTION_ENABLE_MEMORY_SAVINGS=true
OPTION_POINT_IDLETIME=60000
OPTION_WORKINGPATH=e\:\\temp\\data\\
OPTION_EXCEPTION_HANDLING =2
OPTION_ENABLE_MEASUREMENT=true
OPTION_CONFIG_AUTOFILE=true
OPTION_DISABLE_DEVIATION=false

JMX support

For the JMX support i have added two MBeans.
For the configuration you will find a MBean called JmxConfig. This could be used for Java 5 and 6.
For the access to the Measure points you will find a MXBean called JmxPointsMXBean, which will only return a map of JmxPoint for every point.
To start the JMX interface use the method MeasureFactory.registerMBeans(). This will register the MBeans in the standard MBean server deployed with the JRE. For other JMXX implementation please use the registration method for that.
An example for using you can get in the de.mcs.jmeasurement.example.TestApplication

Dependencies of this library

For the persistent storage i need a xml parser. Please add one to the CLASSPATH or use Java 1.4.

Extension points of this library

Reporting

A example using all interfaces you will find in {@link de.mcs.jmeasurement.renderer.DefaultHTMLRenderer DefaultHTMLRenderer}.

Measurement

On the side of the measurement there will be the following extension possibilities.

Perfomancetests

In this package there is a predefined performance test implemented. To start this test simply call

java -cp JMeasurement-0.##.###.jar -Xms256m -Xmx256m de.mcs.jmeasurement.test.Performance 
(Please exchange the ## with the right version informations of your library) The performance test will automatically generate 100000 measurepoints, than it will start for every point a monitor and stop it again. After that it will do the same, but with a disabled factory. After this test it will test the preformance of the interface proxy. It makes 100.000 calls to an interface function once with MeasurementFactory enabled, once with MeasurementFactory disabled. On my 1.5 GHz, 1GB Centrino Nootebook, the results are something like
Report summary
1. :1522 msec
2. :1062 msec
3. :441 msec
4. :1031 msec
5. :371 msec
On my 2 GHz, 2GB Centrino Duo Nootebook, the results are something like
Report summary
1. :1328 msec
2. :703 msec
3. :156 msec
4. :657 msec
5. :172 msec

Usage of third party componentes

In this package only one third party part is integrated. It's the XML Writer package of David Megginson (david@megginson.com) Many Thanks.
Second some inspiration of this package came from the JAMon package (www.jamonapi.com) of Steve Souza - admin@jamonapi.com

License

 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at
 
      http://www.apache.org/licenses/LICENSE-2.0
 
 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.