I need to implement a Web based application that once deployed on tomcat, can monitor active sessions of all applications deployed on same tomcat.
let's say tomcat has 2 applications running as 1) ReportGenerator 2) DataSyncManager. I need to show active sessions for these 2 applications with below stats.
Seesion # Application Session Start Time
1234 ReportGenerator XXXX
56748 DataSyncManager XXXX
55565 DataSyncManager XXXX
Also i have a requirement to kill session on the fly. Is it possible? please advice.
I know this is something similar admin console of tomcat/ was. But i need to implement it as a custom application with custom logging and monitoring feature. Please advice me on which framework/api i can use to capture active sessions on tomcat and their stats.
I have implementated this functionality with a generic approach using standard APIs and specifications, no 3rd party frameworks or libraries. This solution has been used extensively with many enterprise grade systems deployed in glassfish application server and jboss. It has also been used successfully with weblogic (12c). However, the approach should work in any application server or servlet container supporting the standard JMX specification.
The tldr; version of this is to create two JMX bean interfaces and one http session listener. One of the JMX bean interfaces creates one instance per application monitored and is responsible of tracking all sessions from each application being monitored, it basically provides statistics of all sessions for each application. The other JMX bean interface creates one instance for every session created within each monitored application. The http session listener monitors the sessions of each application and does two things. Informs the first JMX bean corresponding to this application about the sessions created/destroyed in order for the statistics to be updated. Registers or unregisters JMX instances corresponding to a session, from the JMX service.
Once everything is setup it can be used from a JMX client like jconsole and visualvm that come with the jdk. From a jmx client it is possible to view all properties of JMX beans and also call any of their methods.
The following screenshots are from a test application using jconsole.
These are attributes from the JMX bean instance corresponding to each application monitored.
These are operations that can be executed on the specific session selected.
If more than one applications are monitored then more app contexts with their own structures will be present i.e. /TestApplication , /Application2 etc under each of the jmx bean interfaces.
HOW TO
Initially it is required to create the two JMX bean interfaces (simple tutorial) and then one HttpSessionListener (plenty of tutorials online).
1.The first JMX bean interface will have only one instance per application monitored and will store all information related to to sessions created from any of the apps monitored. It is basically used for persistence. I only keep the data in memory, which means that the data will be lost if the server goes down but usually it is only required to check the stats as long as the server is up. If you want to persist the data to a log or db in order to always have this information you can certainly do that within the implementation of the interface.
So this could be as follows,
public interface SessionsMXBean {
/**
* Get Indicates whether the data should be persisted in memory.
*/
public boolean getPersistData();
/**
* Set Indicates whether the data should be persisted in memory.
*/
public void setPersistData(boolean value);
/**
* Get All active sessions that have been persisted.
*/
public String getActiveSessions();
/**
* Get All dates of each active session that has been persisted.
*/
public String getDatesOfSessions();
/**
* Get The threshold for the number of session, after which persistence will
* take place. If -1 all are persisted.
*/
public int getSessionsThreshold();
/**
* Set The threshold for the number of session, after which persistence will
* take place. If -1 all are persisted.
*/
public void setSessionsThreshold(int value);
/**
* Set The limit of size to be persisted in KB. If -1 then no size limit.
*/
public void setPersistenceSize(long value);
/**
* Clears all persisted data.
*/
public void clearData();
/**
* Unregisters this instance
*/
public void unregisterThis();
}
Then you have to create an implementation of this interface that will eventually hold this kind of data.
public class SessionsImpl implements SessionsMXBean {
/*
here you need to implement the interface and have all kind of objects you require
*/
public synchronized void incrementSessions() {
....
}
public synchronized void decrementSessions() {
.....
}
2.The second JMX bean interface will have one instance for every session created in each one of your monitored apps. This interface will store the session object and will also have methods that can be called from a jmx client, to invalidate those sessions. This can be as follows,
public interface HttpSessionMXBean {
/**
* Get HTTP Session id
*/
public String getSessionId();
/**
* Get the date created
*/
public String getDateCreated();
/**
* Get the date created in milliseconds
*/
public long getMillisCreated();
/**
* Get attributes from http session
*
* @param attrName Attribute Name
* @return java.lang.String
*/
public String getAttribute(String attrName);
/**
* Invalidate this session
*/
public void invalidate();
/**
* Unregisters this instance
*/
public void unregisterThis();
}
And again an implementation is required,
public class HttpSessionMXBeanImpl implements HttpSessionMXBean {
....
3.Then you create the HttpSessionListener that will create/remove instances of the 2nd bean interface and register/unregister them from your server's JMX service. This will happen as the sessions are created and invalidated/expired. So you will have one listener per application that has it defined in its web.xml.
HttpSessionListener
....
public class MyJMXHTTPSessionListener implements HttpSessionListener {
....
private SessionsImpl sesssionsImpl;
private Map<String, HttpSessionMXBeanImpl> httpSessionMXBeans
@Override
public void sessionCreated(HttpSessionEvent se) {
//requires synchronized block here with this i.e.
synchronized (this) {
/*check if a jmx bean instance of the 1st interface exists otherwise create one*/
if(sessionsImpl==null){
sesssionsImpl= new SesssionsImpl();
/* take care here to create a nice and unique path per instance
of the application in order to be nicely presented on the JMX tree of the JMX clients */
String id = ("services.jmx.beans:type=Sessions,"+ "realm=" + se.getSession().getServletContext().getContextPath());
sessionManagerMXBean.setId(id);
ObjectName objectName = new ObjectName(id);
if (ManagementFactory.getPlatformMBeanServer().isRegistered(objectName)) {
ManagementFactory.getPlatformMBeanServer().
unregisterMBean(objectName);
}
ManagementFactory.getPlatformMBeanServer().
registerMBean(sesssionsImpl,
objectName);
}
sesssionsImpl.inrementSessions();
/*
create a jmx bean instance of the 2nd interface
and register it to the jmx service as already shown using the unique session id
and a nice path indicating the 2nd interface jmx beans.
*/
}
@Override
public void sessionDestroyed(HttpSessionEvent se) {
//requires synchronized block here with this i.e.
synchronized (this) {
/*unregister the jmx bean instance of the 2nd interface,
remove it from the list
and call decrementSessions() on the jmx bean instance corresponding to this app*/
}
}
}
This functionality can be easily activated anytime for any web app if you define the HttpSessionListener within web.xml file by adding the following few lines,
web.xml
<listener>
<listener-class>
myservices.myhttpsessionlisteners.MyJMXHTTPSessionListener
</listener-class>
</listener>
Did you check out the psi-probe project?
It is an advanced manager and monitor for Apache Tomcat, forked from Lambda Probe.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With