26

I am developing a project in Java in which I want the count of all active sessions in Tomcat. Based on that I want to see how much of those users are active and actually using the application.

Jasper
  • 2,166
  • 4
  • 30
  • 50
rampatel
  • 521
  • 3
  • 10
  • 17

9 Answers9

21

You should use JMX (Java Managemnet eXtension) and query the following

jmxObjectName:    Catalina:host=localhost,path=/,type=Manager
jmxAttributeName: activeSessions

You can use jconsole to access this data. To get jmx running see http://tomcat.apache.org/tomcat-6.0-doc/monitoring.html

You have lot of advantages using JMX as you get lots of other data, too. You can put it in a munin plugin and let munin monitor it and draw nice graphs to look at.

Janning Vygen
  • 8,877
  • 9
  • 71
  • 102
  • 3
    Can anybody post a code snippet that shows how to retrieve the activeSessions via JMX from within the JVM itself? – basZero Jun 22 '15 at 07:50
18

There isn't any way to get the session count directly from tomcat. But you can create and register a session listener and up the count when its created. Here is an example:

http://tomcat-configure.blogspot.com/2009/01/tomcat-session-listener-example.html

public class SessionCounter implements HttpSessionListener {

  private static int activeSessions = 0;

  public void sessionCreated(HttpSessionEvent se) {
    activeSessions++;
  }

  public void sessionDestroyed(HttpSessionEvent se) {
    if(activeSessions > 0)
      activeSessions--;
    }

  public static int getActiveSessions() {
     return activeSessions;
  }
}
Amir Raminfar
  • 33,777
  • 7
  • 93
  • 123
  • 1
    From the listener, you should be able to cast the HttpSession to org.apache.catalina.session.StandardSession if you need any Tomcat specific data. – AngerClown Nov 01 '10 at 14:41
  • @user, if this solved your problem then please accept the right answer :) – Amir Raminfar Nov 02 '10 at 18:44
  • Thanks for comment but listener understand the session destroy reason of session time out.? – rampatel Nov 03 '10 at 05:11
  • I am not sure what you are asking? Can you try rewording please :) – Amir Raminfar Nov 03 '10 at 13:54
  • You can get the count directly from tomcat via JMX, see my answer below. Jmx is the way to go! JMX does show active Sessions and an all time maximum (and lots of other data like request count, response times etc.). And it respects destroyed sessions, of course – Janning Vygen Jun 21 '12 at 14:29
  • This answer does not seem to be as good as the other answer proposing to use JMX. Implementing yet another counter is superfluous, I would recommend to use JMX as described [here](http://stackoverflow.com/a/11140382/356815) – basZero Jul 14 '14 at 09:04
  • 1
    if you used this approach and stored references to the sessions themselves in a Map which was a member variable of the filter, would that be a very bad idea (because the sessions then would not be able to be GCed)? – Black Jan 26 '15 at 12:56
5

Here is the Java 7 style JMX code snippet (what basZero asked for and exactly does the job what Janning described):

JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:9999/jmxrmi");
try(JMXConnector jmxc = JMXConnectorFactory.connect(url)) {
  MBeanServerConnection mbsc = jmxc.getMBeanServerConnection();
  ObjectName mbeanName = new ObjectName("Catalina:type=Manager,context=/,host=localhost");
  Object value = mbsc.getAttribute(mbeanName, "activeSessions");
}

Of course you need to replace root context (/) in ObjectName with your app context string if it is not deployed in the root context. See my detailed explanation on the Catalina JMX issue here: Accessing built-in MBeans in Tomcat programatically

Community
  • 1
  • 1
Miklos Krivan
  • 1,732
  • 20
  • 14
4

A simple tutorial to demonstrate how to determine active users / sessions in a Java Web Application.

package com.hubberspot.javaee.listener;

import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

@WebListener
public class OnlineUsersCounter implements HttpSessionListener {

private static int numberOfUsersOnline;

 public OnlineUsersCounter() {
  numberOfUsersOnline = 0;
 }

 public static int getNumberOfUsersOnline() { 
  return numberOfUsersOnline;
 }

    public void sessionCreated(HttpSessionEvent event) {

     System.out.println("Session created by Id : " + event.getSession().getId());
     synchronized (this) {
   numberOfUsersOnline++;
  }

    }

    public void sessionDestroyed(HttpSessionEvent event) {

     System.out.println("Session destroyed by Id : " + event.getSession().getId());
     synchronized (this) {
   numberOfUsersOnline--;
  }

    }

}

Running the below servlet on three different browsers will provide output as : (see fig below)

package com.hubberspot.javaee;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebInitParam;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import com.hubberspot.javaee.listener.OnlineUsersCounter;

// @WebServlet annotation has a initParams field which takes
// in initialization parameters for a servlet.
// @WebInitParam annotation takes in a name and value for the
// initialization parameters for the current Servlet.

@WebServlet(name = "HelloWorldServlet" , urlPatterns = { "/HelloWorldServlet" }
, initParams = { @WebInitParam(name = "user" , value = "Jonty") })
public class HelloWorldServlet extends HttpServlet {

 protected void doGet(
   HttpServletRequest request, 
   HttpServletResponse response
   ) throws ServletException, IOException {

  response.setContentType("text/html");

  PrintWriter out = response.getWriter();

  // sessionCreated method gets executed
  HttpSession session = request.getSession();

  session.setMaxInactiveInterval(60);

  try {
   out.println("<html>");
   out.println("<body>");
   out.println("<h2>Number of Users Online : "
      + OnlineUsersCounter.getNumberOfUsersOnline() 
      + "</h2>");
   out.println("</body>");
   out.println("</html>");
  } finally {
   out.close();
  }

 }

}

Output of the program :

  1. Eclipse Browser ->

Eclipse

  1. Firefox Browser ->

Firefox

  1. Internet Explorer Browser ->

IE

  1. Console Output ->

Console

For more: http://www.hubberspot.com/2013/09/how-to-determine-active-users-sessions.html

Yash P Shah
  • 779
  • 11
  • 15
3

Here is how to get the session count locally, if you're getting the stats within an application running on the tomcat server you want the stats for. No need to enable jmx remote this way:

public void init(final ServletConfig config) throws ServletException
{
    context = config.getServletContext().getContextPath();
}
//...
private void getSessionStats()
{
    MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();
    ObjectName objectName = new ObjectName("Catalina:type=Manager,context="+context+",host=localhost");
    Object activeSessions = mBeanServer.getAttribute(objectName, "activeSessions");
    System.out.println(activeSessions);
}
AdeelMufti
  • 341
  • 1
  • 8
2

If you dont need the values in the actual web application, a groovy script can help:

import javax.management.remote.*
import javax.management.*
import groovy.jmx.builder.*

// Setup JMX connection.
def connection = new JmxBuilder().client(port: 4934, host: '192.168.10.6')
connection.connect()

// Get the MBeanServer.
def mbeans = connection.MBeanServerConnection

def activeBean = new GroovyMBean(mbeans, 'Catalina:type=Manager,host=localhost,context=/')
println "Active sessions: " + activeBean['activeSessions']

If you want the actual sessions, you have methods to retrieve them, like:

def sessions = activeBean.listSessionIds().tokenize(' ');
Brimstedt
  • 3,020
  • 22
  • 32
1

"PSI Probe" may do the trick for you: http://code.google.com/p/psi-probe/

FelixD
  • 629
  • 7
  • 17
0

You can attach a jolokia jvm agent to the running tomcat and query the activeSessions attribute from the relevant MBeans via curl.

java -jar agent.jar start [TOMCAT-PID]
curl 'http://127.0.0.1:8778/jolokia/read/Catalina:context=*,host=*,type=Manager/activeSessions'
java -jar agent.jar stop [TOMCAT-PID]

This will give you something like

{  
   "request":{  
      "mbean":"Catalina:context=*,host=*,type=Manager",
      "attribute":"activeSessions",
      "type":"read"
   },
   "value":{  
      "Catalina:context=\/SampleApp,host=localhost,type=Manager":{  
         "activeSessions":1
      }
   },
   "timestamp":1553105659,
   "status":200
}
visit1985
  • 468
  • 4
  • 14
0

Two more approaches to add, both of which I've been using all the time.

1. VisualVM

To find out the number of active sessions, you can use Tomcat's internal statistics that can be accessed using JMX (Java Management Extension).

Practically, a profiling tool such as VisualVM or Java VisualVM can be used to access the JMX statistics, such as the number of active sessions, on the MBeans tab (See below the screenshot)

enter image description here

2. JavaMelody

You can also use a JavaEE applications monitoring tool, such as JavaMelody, which helps you monitor Java or Java EE applications in QA and production environments.

enter image description here

Yuci
  • 27,235
  • 10
  • 114
  • 113