Statistics and JMX

126 views
Skip to first unread message

Gérald

unread,
Dec 13, 2011, 10:49:54 AM12/13/11
to javasimon
Hello,

I am a former JAMon user and giving JavaSimon a try.

How can I have some simple statistics: Avg, Min, Max, Total, Hits, Std
Dev?
Can I see them in JMX?
Is it possible to have those timings in ms in JMX (so as to draw
graphs with JConsole)?

Thanx for your help

Richard Richter

unread,
Dec 13, 2011, 11:21:11 AM12/13/11
to java...@googlegroups.com
Hi Gerald

I'm not sure about ms times, we have only nanos in raw form. Everything we provide is available in Stopwatch.getSample(). Check JmxTaskProcessingSimulator example and the attached screenshot. I hope this gives you the basic idea.
There is alternative way - check org.javasimon.examples.jmx.JmxCallbackExample source code for MX bean per Simon.

Cheers :-)

Virgo


--
You received this message because you are subscribed to the Google Groups "javasimon" group.
To post to this group, send email to java...@googlegroups.com.
To unsubscribe from this group, send email to javasimon+...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/javasimon?hl=en.


JmxTaskProcessingSimulator-with-jconsole.png

Gérald

unread,
Dec 13, 2011, 2:33:33 PM12/13/11
to javasimon
Thanx Richard,

I regret that StopwatchMXBeanImpl, JmxRegisterCallback,
SimonMXBeanImpl, SimonInfo, etc. are not designed for extension (final
methods, private fields with no public getter), I guess I'll have to
rewrite them completely just to add avg/min/max fields expressed in
milliseconds (nanonseconds precision is useless is my case).

Gérald

>  JmxTaskProcessingSimulator-with-jconsole.png
> 275KAfficherTélécharger

Richard Richter

unread,
Dec 13, 2011, 3:04:25 PM12/13/11
to java...@googlegroups.com
Hi Gerald

I'm sorry for that but it's much more difficult to satisfy all needs and implement stuff designed for extension so it is good, nice and prepared for everything. You can either rewrite it or wrap it and delegate the stuff to our beans with adding only what you need.

Also too bad you can't convert the stuff on the JMX client side somehow. I still hope Simon is usefull in overall, even if it needs some customization.

Cheers

Virgo

Gérald

unread,
Dec 17, 2011, 9:41:08 AM12/17/11
to javasimon
I don't know what's the best way to propose a patch (I can send it by
mail provided I have an address)

I split StopwatchMXBeanImpl in 2: StopwatchMXBeanImpl
+BaseStopwatchMXBeanImpl
The Custom* classes are just examples, my CustomStopwatchMXBeanImpl
extends BaseStopwatchMXBeanImpl
There shouldn't be any impact on existing projects.

Here is the patch:

# This patch file was generated by NetBeans IDE
# Following Index: paths are relative to: C:\Java\javasimon-3.0.0\trunk
\core\src\main\java\org\javasimon\jmx
# This patch can be applied using context Tools: Patch action on
respective folder.
# It uses platform neutral UTF-8 encoding and \n newlines.
# Above lines and this line are ignored by the patching process.
Index: BaseStopwatchMXBeanImpl.java
--- BaseStopwatchMXBeanImpl.java Locally New
+++ BaseStopwatchMXBeanImpl.java Locally New
@@ -0,0 +1,63 @@
+package org.javasimon.jmx;
+
+import org.javasimon.Stopwatch;
+import org.javasimon.Simon;
+
+/**
+ * MX Bean representing a particular {@link
org.javasimon.Stopwatch}.
+ * It can be used as base for developping custom Stopwatch JMX beans
+ *
+ * @author <a href="mailto:vir...@gmail.com">Richard "Virgo"
Richter</a>
+ */
+public class BaseStopwatchMXBeanImpl extends AbstractSimonMXBeanImpl
{
+ private final Stopwatch stopwatch;
+
+ /**
+ * Creates the MX bean for the provided Stopwatch.
+ *
+ * @param stopwatch wrapped Stopwatch
+ */
+ public BaseStopwatchMXBeanImpl(Stopwatch stopwatch) {
+ this.stopwatch = stopwatch;
+ }
+
+ /**
+ * Return associated Stopwatch Simon
+ * @return Stopwatch
+ */
+ public Stopwatch getStopwatch() {
+ return stopwatch;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final StopwatchSample sample() {
+ return new StopwatchSample(stopwatch.sample());
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final StopwatchSample sampleAndReset() {
+ return new StopwatchSample(stopwatch.sampleAndReset());
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected final Simon simon() {
+ return stopwatch;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final String getType() {
+ return SimonInfo.STOPWATCH;
+ }
+}
Index: custom/CustomJmxRegisterCallback.java
--- custom/CustomJmxRegisterCallback.java Locally New
+++ custom/CustomJmxRegisterCallback.java Locally New
@@ -0,0 +1,38 @@
+package org.javasimon.jmx.custom;
+
+import javax.management.MBeanServer;
+import org.javasimon.Simon;
+import org.javasimon.Stopwatch;
+import org.javasimon.jmx.JmxRegisterCallback;
+import org.javasimon.jmx.SimonSuperMXBean;
+
+/**
+ * Customized JMX register callback.
+ * Register CustomStopwatchMXBeanImpl instead of usual
StopwatchMXBeanImpl
+ * @author <a href="mailto:gerald....@gmail.com">Gerald
Quintana</a>
+ */
+public class CustomJmxRegisterCallback extends JmxRegisterCallback {
+
+ public CustomJmxRegisterCallback(MBeanServer mBeanServer) {
+ super(mBeanServer);
+ }
+
+ public CustomJmxRegisterCallback() {
+ }
+
+ @Override
+ protected SimonSuperMXBean constructObject(Simon simon) {
+ if (simon instanceof Stopwatch) {
+ return new CustomStopwatchMXBeanImpl((Stopwatch) simon);
+ } else {
+ return super.constructObject(simon);
+ }
+ }
+
+ @Override
+ protected String constructObjectName(Simon simon) {
+ return "com.mycompany.myapp:type=Simon,name="+simon.getName()
+",kind=" + simonType(simon);
+ }
+
+
+}
Index: custom/CustomStopwatchMXBean.java
--- custom/CustomStopwatchMXBean.java Locally New
+++ custom/CustomStopwatchMXBean.java Locally New
@@ -0,0 +1,29 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.javasimon.jmx.custom;
+
+import org.javasimon.jmx.SimonSuperMXBean;
+
+/**
+ *
+ * @author gquintana
+ */
+public interface CustomStopwatchMXBean extends SimonSuperMXBean {
+
+ long getCounter();
+
+ long getLast();
+
+ long getMax();
+
+ double getMean();
+
+ long getMin();
+
+ double getStandardDeviation();
+
+ long getTotal();
+
+}
Index: custom/CustomStopwatchMXBeanImpl.java
--- custom/CustomStopwatchMXBeanImpl.java Locally New
+++ custom/CustomStopwatchMXBeanImpl.java Locally New
@@ -0,0 +1,51 @@
+package org.javasimon.jmx.custom;
+
+import org.javasimon.Stopwatch;
+import org.javasimon.jmx.BaseStopwatchMXBeanImpl;
+
+/**
+ * Customized Stopwatch JMX bean displaying values in milliseconds
+ * @author <a href="mailto:gerald....@gmail.com">Gerald
Quintana</a>
+ */
+public class CustomStopwatchMXBeanImpl extends
BaseStopwatchMXBeanImpl implements CustomStopwatchMXBean {
+
+ public CustomStopwatchMXBeanImpl(Stopwatch stopwatch) {
+ super(stopwatch);
+ }
+
+ private final double nanosToMillis(double nanos) {
+ return nanos/1000000d;
+ }
+ private final long nanosToMillis(long nanos) {
+ return nanos/1000000L;
+ }
+ @Override
+ public double getMean() {
+ return nanosToMillis(getStopwatch().getMean());
+ }
+ @Override
+ public long getMin() {
+ return nanosToMillis(getStopwatch().getMin());
+ }
+ @Override
+ public long getMax() {
+ return nanosToMillis(getStopwatch().getMax());
+ }
+ @Override
+ public long getTotal() {
+ return nanosToMillis(getStopwatch().getTotal());
+ }
+ @Override
+ public long getLast() {
+ return nanosToMillis(getStopwatch().getLast());
+ }
+ @Override
+ public long getCounter() {
+ return getStopwatch().getCounter();
+ }
+ @Override
+ public double getStandardDeviation() {
+ return nanosToMillis(getStopwatch().getStandardDeviation());
+ }
+
+}
Index: JmxRegisterCallback.java
--- JmxRegisterCallback.java Base (BASE)
+++ JmxRegisterCallback.java Locally Modified (Based On LOCAL)
@@ -20,8 +20,20 @@
* @author <a href="mailto:vir...@gmail.com">Richard "Virgo"
Richter</a>
*/
public class JmxRegisterCallback extends CallbackSkeleton {
- private MBeanServer mBeanServer =
ManagementFactory.getPlatformMBeanServer();
+ private MBeanServer mBeanServer;
private Set<String> registeredNames = new HashSet<String>();
+ /**
+ * Default constructor uses default MBeanServer
+ */
+ public JmxRegisterCallback() {
+
this.mBeanServer=ManagementFactory.getPlatformMBeanServer();
+ }
+ /**
+ * Constructor using specific MBeanServer
+ */
+ public JmxRegisterCallback(MBeanServer mBeanServer) {
+ this.mBeanServer=mBeanServer;
+ }

/**
* After Simon is created respective MX bean is registered for it
according to
@@ -82,16 +94,9 @@
* @param simon Simon MX Bean to be registered
*/
protected final void register(Simon simon) {
- SimonSuperMXBean simonMxBean;
- if (simon instanceof Counter) {
- simonMxBean = new CounterMXBeanImpl((Counter) simon);
- } else if (simon instanceof Stopwatch) {
- simonMxBean = new StopwatchMXBeanImpl((Stopwatch) simon);
- } else {
- warning("Unknown type of Simon! " + simon, null);
- return;
- }
+ Object mBean=constructObject(simon);
String name = constructObjectName(simon);
+ if (mBean!=null && name!=null) {
try {
ObjectName objectName = new ObjectName(name);
if (mBeanServer.isRegistered(objectName)) {
@@ -99,15 +104,34 @@
} else {
registeredNames.add(name);
}
- mBeanServer.registerMBean(simonMxBean, objectName);
+ mBeanServer.registerMBean(mBean,
objectName);
message("Simon registered under the name: " + objectName);
} catch (JMException e) {
warning("JMX registration failed for: " + name, e);
registeredNames.remove(name);
}
}
+ }

/**
+ * Constructs JMX object from Simon object. Method can be
overridden.
+ *
+ * @param simon Simon object
+ * @return JMX object (=MBean) representing the Simon
+ */
+ protected SimonSuperMXBean constructObject(Simon simon) {
+ SimonSuperMXBean simonMxBean;
+ if (simon instanceof Counter) {
+ simonMxBean = new CounterMXBeanImpl((Counter) simon);
+ } else if (simon instanceof Stopwatch) {
+ simonMxBean = new StopwatchMXBeanImpl((Stopwatch) simon);
+ } else {
+ warning("Unknown type of Simon! " + simon, null);
+ simonMxBean=null;
+ }
+ return simonMxBean;
+ }
+ /**
* Constructs JMX object name from Simon object. Method can be
overridden.
*
* @param simon Simon object
Index: StopwatchMXBeanImpl.java
--- StopwatchMXBeanImpl.java Base (BASE)
+++ StopwatchMXBeanImpl.java Locally Modified (Based On LOCAL)
@@ -1,7 +1,6 @@
package org.javasimon.jmx;

import org.javasimon.Stopwatch;
-import org.javasimon.Simon;
import org.javasimon.utils.SimonUtils;

/**
@@ -11,8 +10,7 @@
*
* @author <a href="mailto:vir...@gmail.com">Richard "Virgo"
Richter</a>
*/
-public class StopwatchMXBeanImpl extends AbstractSimonMXBeanImpl
implements StopwatchMXBean {
- private Stopwatch stopwatch;
+public class StopwatchMXBeanImpl extends BaseStopwatchMXBeanImpl
implements StopwatchMXBean {

/**
* Creates the MX bean for the provided Stopwatch.
@@ -20,7 +18,7 @@
* @param stopwatch wrapped Stopwatch
*/
public StopwatchMXBeanImpl(Stopwatch stopwatch) {
- this.stopwatch = stopwatch;
+ super(stopwatch);
}

/**
@@ -28,7 +26,7 @@
*/
@Override
public final void addTime(long ns) {
- stopwatch.addTime(ns);
+ getStopwatch().addTime(ns);
}

/**
@@ -36,7 +34,7 @@
*/
@Override
public final long getLast() {
- return stopwatch.getLast();
+ return getStopwatch().getLast();
}

/**
@@ -47,35 +45,4 @@
return SimonUtils.presentNanoTime(getLast());
}

- /**
- * {@inheritDoc}
- */
- @Override
- public final StopwatchSample sample() {
- return new StopwatchSample(stopwatch.sample());
}
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final StopwatchSample sampleAndReset() {
- return new StopwatchSample(stopwatch.sampleAndReset());
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- protected final Simon simon() {
- return stopwatch;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final String getType() {
- return SimonInfo.STOPWATCH;
- }
-}

Richard Richter

unread,
Dec 17, 2011, 3:11:21 PM12/17/11
to java...@googlegroups.com
Thanks for the patch, seems reasonable. Please, send me the patch as an attachment. From the look of it, line breaks (additional and unexpected) from mail formatting seems to be the problem :-)

Of course, I'll have to redo the Counters in the similar way just to be consistent, but that's the least of it.

Virgo

Gérald Quintana

unread,
Dec 17, 2011, 3:52:31 PM12/17/11
to java...@googlegroups.com, vir...@gmail.com
Thanks for your agreement.

The patch is attached.Agree with you about Counters, this patch was
more a proof of concept. I can do it this week, if you're too busy...

The second one is a minor improvement on the EJB interceptor to make
simon names easily customisable (exactly like the Servlet Filter).

Cheers,
Gérald


2011/12/17 Richard Richter <vir...@gmail.com>:

javasimon-core-jmx.patch
javasimon-javee-ejb-interceptor.patch
Reply all
Reply to author
Forward
0 new messages