NOTE: This is outdated information that applies only to Tapestry 3 & 4. For current information see http://tapestry.apache.org/current/tapestry-jmx/project-summary.html |
Here is my preliminary code that enables JMX monitoring of Tapestry. It is based on the IMonitor interface. It requires 4 classes and a declaration inside the .application file: <extension name="org.apache.tapestry.monitor-factory" class="actualis.web.tapestry.jmx.MonitorFactory" />
The main issue with this code is that the MBeans can not be released when the application is undeployed or redeployed. A solution could be to extend the ApplicationServlet class and use the destroy() method to release them. Maybe with Tapestry 4 it would be possible to plug the MBeans into the hivemind registry and let it release them?
package actualis.web.tapestry.jmx;
public interface ServiceMBean {
/**
* @return Returns the serviceTime.
*/
public abstract double getServiceTime();
}package actualis.web.tapestry.jmx;
public class Service implements ServiceMBean {
private String serviceName;
public Service(String serviceName) {
this.serviceName = serviceName;
}
double serviceStart;
double serviceTime;
/* (non-Javadoc)
* @see actualis.web.tapestry.jmx.ServiceMBean#getServiceTime()
*/
public final double getServiceTime() {
return serviceTime;
}
}package actualis.web.tapestry.jmx;
public interface PageMBean {
/**
* @return Returns the createTime.
*/
public abstract double getCreateTime();
/**
* @return Returns the createTime.
*/
public abstract double getLoadTime();
/**
* @return Returns the renderTime.
*/
public abstract double getRenderTime();
/**
* @return Returns the rewindTime.
*/
public abstract double getRewindTime();
}package actualis.web.tapestry.jmx;
public class Page implements PageMBean {
private String pageName;
double createTime;
double loadTime;
double renderTime;
double rewindTime;
double createStart;
double loadStart;
double renderStart;
double rewindStart;
/* (non-Javadoc)
* @see actualis.web.tapestry.jmx.PageMBean#getCreateTime()
*/
public final double getCreateTime() {
return createTime;
}
/* (non-Javadoc)
* @see actualis.web.tapestry.jmx.PageMBean#getLoadTime()
*/
public final double getLoadTime() {
return loadTime;
}
/* (non-Javadoc)
* @see actualis.web.tapestry.jmx.PageMBean#getPageName()
*/
public final String getPageName() {
return pageName;
}
/* (non-Javadoc)
* @see actualis.web.tapestry.jmx.PageMBean#getRenderTime()
*/
public final double getRenderTime() {
return renderTime;
}
/* (non-Javadoc)
* @see actualis.web.tapestry.jmx.PageMBean#getRewindTime()
*/
public final double getRewindTime() {
return rewindTime;
}
public Page(String pageName) {
this.pageName = pageName;
}
}package actualis.web.tapestry.jmx;
import org.apache.tapestry.engine.IMonitor;
import org.apache.tapestry.engine.IMonitorFactory;
import org.apache.tapestry.request.RequestContext;
public class MonitorFactory implements IMonitorFactory {
private static IMonitor MONITOR = new Monitor();
public IMonitor createMonitor(RequestContext context) {
return MONITOR;
}
}package actualis.web.tapestry.jmx;
import java.lang.management.ManagementFactory;
import java.util.HashMap;
import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import org.apache.log4j.Logger;
import org.apache.tapestry.engine.IMonitor;
public class Monitor implements IMonitor {
/**
* Logger for this class
*/
private static final Logger s_logger = Logger.getLogger(Monitor.class);
private HashMap<String, Page> page_mbeans = new HashMap<String, Page>();
private HashMap<String, Service> service_mbeans = new HashMap<String, Service>();
public Page getPageMBean(String pageName) {
Page res = page_mbeans.get(pageName);
if (res == null) {
res = new Page(pageName);
MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
ObjectName name;
try {
name = new ObjectName("Tapestry:type=Pages,name=" + pageName);
mbs.registerMBean(res, name);
} catch (Exception e) {
s_logger.warn("Impossible to register mbean", e);
}
page_mbeans.put(pageName, res);
}
return res;
}
public Service getServiceMBean(String serviceName) {
Service res = service_mbeans.get(serviceName);
if (res == null) {
res = new Service(serviceName);
MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
ObjectName name;
try {
name = new ObjectName("Tapestry:type=Services,name=" + serviceName);
mbs.registerMBean(res, name);
} catch (Exception e) {
s_logger.warn("Impossible to register mbean", e);
}
service_mbeans.put(serviceName, res);
}
return res;
}
public void pageCreateBegin(String pageName) {
Page pmb = getPageMBean(pageName);
pmb.createStart = System.currentTimeMillis();
}
public void pageCreateEnd(String pageName) {
Page pmb = getPageMBean(pageName);
pmb.createTime = System.currentTimeMillis() - pmb.createStart; }
public void pageLoadBegin(String pageName) {
Page pmb = getPageMBean(pageName);
pmb.loadStart = System.currentTimeMillis();
}
public void pageLoadEnd(String pageName) {
Page pmb = getPageMBean(pageName);
pmb.loadTime = System.currentTimeMillis() - pmb.loadStart;
}
public void pageRenderBegin(String pageName) {
Page pmb = getPageMBean(pageName);
pmb.renderStart = System.currentTimeMillis();
}
public void pageRenderEnd(String pageName) {
Page pmb = getPageMBean(pageName);
pmb.renderTime = System.currentTimeMillis() - pmb.renderStart;
}
public void pageRewindBegin(String pageName) {
Page pmb = getPageMBean(pageName);
pmb.rewindStart = System.currentTimeMillis();
}
public void pageRewindEnd(String pageName) {
Page pmb = getPageMBean(pageName);
pmb.rewindTime = System.currentTimeMillis() - pmb.rewindStart;
}
public void serviceBegin(String serviceName, String detailMessage) {
Service serv = getServiceMBean(serviceName);
serv.serviceStart = System.currentTimeMillis();
}
public void serviceEnd(String serviceName) {
Service serv = getServiceMBean(serviceName);
serv.serviceTime = System.currentTimeMillis() - serv.serviceStart;
}
public void serviceException(Throwable exception) {
// Intentional
}
public void sessionBegin() {
// Intentional
}
}