The reasons of this little project

Recently I had a little problem on a Websphere application server. A JSP page running on this application server had a problem (a no ending loop). This was a bit hard to identify because noting permit to isolate on this server the pages running.
To solve this lake of informations I realized a little Servletfilter which permit to monitor this.
I propose you this little tool for exemple as a ServletFilter. I wish it would be useful to you.



The goal of the project.

It consist to put in a HashTable the running pages. I also had some others informations which permit me to offer some more statistics (execution time, number of errors, number of executions…)
A JSP page display the informations of this Hashtable.

The use of this filter allows me to add this option to the whole webapps without changing the actif code (only the file web.xml which have to be modifiate to activate the filter).


Project source

The whole source code is avaible to download. The application is composed of three smalls classes :

StatsFilter.java : The filter

Little class doing all his work in the methoddoFilter

package com.berthou.web.filtre;
 
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
 
public final class StatsFilter implements Filter {
    private FilterConfig filterConfig = null;
    private String appli = "" ;
 
    public void doFilter(ServletRequest request, ServletResponse response,
        FilterChain chain) throws IOException, ServletException {
        if (filterConfig == null)  return;
 
        String key = "" ;
    	long startTime = System.currentTimeMillis();
        try {
    		key = appli + ((HttpServletRequest)request).getServletPath() ;
    		// On ajoute la page dans la liste des pages en cours
    		MonitorJsp.action( MonitorJsp.ACT_ADD, key, 0) ;
    		chain.doFilter(request, response);
    		// On supprime la page dans la liste des pages en cours (+temsp d'execution)
    		MonitorJsp.action( MonitorJsp.ACT_DEL, key, (System.currentTimeMillis() - startTime) ) ;
        } catch (IOException io) {
    		// Une erreur ce produit => on la trace puis on la renvoie
    		MonitorJsp.action( MonitorJsp.ACT_ERR, key, (System.currentTimeMillis() - startTime) ) ;
    		throw io ;
        } catch (ServletException se) {
    		// Une erreur ce produit => on la trace puis on la renvoie
    		MonitorJsp.action( MonitorJsp.ACT_ERR, key, (System.currentTimeMillis() - startTime) ) ;
    		throw se ;
        }
    }
    /**
     * Lecture des paramètres d'exécution (dans web.xml)
     *  Ici uniquement la zone APPLICATION
     */
    public void init(FilterConfig filterConfig) throws ServletException {
	this.filterConfig = filterConfig;
	appli = filterConfig.getInitParameter("APPLICATION") ;
    }
 
    public void destroy() {
	this.filterConfig = null;
    }
}

MonitorJsp.java : The monitor

It is a static class of supervision (it is possible to change to a singleton)

package com.berthou.web.filtre;
 
import java.text.SimpleDateFormat;
import java.util.*;
import java.io.* ;
 
/**
 * Classe de suppervision permettant de suivre l'état de certains objets
 * c'est un classe <b>static</b>
 *
 * @author rberthou
 *
 */
public class MonitorJsp {
	public static final String version = "MonitorJsp V1.00 du 4 Septembre 2008";
 
	static protected Hashtable map = new Hashtable(100);
 
	static final int ACT_ADD = 1 ;
	static final int ACT_DEL = 2 ;
	static final int ACT_ERR = 5 ;
 
    public static synchronized void action(int act, String key, long delay) {
 
    	ItemMonitor itm = (ItemMonitor)map.get(key) ;
    	if ( itm == null ) {
    		if (act == ACT_ADD) {
    			itm = new ItemMonitor() ;
    			map.put(key, itm) ;
    		}
    	} else {
			if (act == ACT_ADD) itm.add() ; 	       else
   			if (act == ACT_DEL) itm.remove(delay) ; else
   			if (act == ACT_ERR) itm.error(delay) ;
    	}
    }
    ..... [CUT] ....
  }

ItemMonitor.java : The data

It is a representation of a list of element.

package com.berthou.web.filtre;
 
public class ItemMonitor {
	private long nbrun  = 0  ; // Nombre d'execution
	private long nbact = 0 ;   // Nombre de page active
	private long nberr = 0 ;    // Nombre d'erreur
	private long mints = 0 ;    // Temps min
	private long maxts = 0 ;   // Temps Max
	private long lastAcc = 0 ; // date last exec
 
	/**
	 * Constructeur
	 */
	public ItemMonitor() {
		this.add() ;
	}
 
	public void reset() {
		nbrun  = 0  ;
		nberr = 0 ;
		mints = 0 ;
		maxts = 0 ;
	}
 
	public void add() {
		nbact++ ;
		lastAcc = System.currentTimeMillis() ;
	}
 
	public void remove(long delay) {
		nbrun++ ;
		nbact-- ;
 
		sumts += delay ;
		if (mints < 1 || delay < mints) mints = delay ;
		if (delay > maxts) maxts = delay ;
	}
 
	public void error(long delay) {
		nberr++ ;
		nbact-- ;
	}
      ..... [CUT] .....
}



Utilisation

To use this filter you have to :

  • Add the archive .jar in the collective librairies of your application server. (Be careful: if you put it at once in your directory /WEB-INF/lib of your webapp it will only work for this application.)
  • Change the file web.xml to parameter this filter (exemple just below).
    <filter>
      <filter-name>StatsFilter</filter-name>
      <filter-class>com.berthou.web.flitre.StatsFilter</filter-class>
      <init-param>
          <param-name>APPLICATION</param-name>
          <param-value>TEST1</param-value>
      </init-param>
    </filter>
 
    <filter-mapping>
       <filter-name>StatsFilter</filter-name>
       <url-pattern>*.jsp</url-pattern>
    </filter-mapping>

It allows you to identify the filter in your webapp. You just have to write a JSP page as the one below to display the current datas

<%@ import="com.berthou.web.filtre.*,java.util.*"%>
<%
	// Get iterator for keys in HashMap
	Hashtable monitorSession = (Hashtable)MonitorJsp.cloneIt("b");
	Iterator sessionIter     = monitorSession.keySet().iterator();
	String id = "" ;
	ItemMonitor itm = null ;
%>
<table><thead><tr>
  <th>id</th><th>act</th><th>run</th><th>err</th><th>last</th><th>min/max</th><th>Sum</th>
</tr></thead>
<tbody><%
while(sessionIter.hasNext() ) {
  id = (String)sessionIter.next();
  itm = (ItemMonitor)monitorSession.get(id);
  try
  {
		%><tr valign="top"><td ><%=id%></td><%=itm.toHtmlString()%></tr><%
  }
  catch ( java.lang.IllegalStateException ie ) {
  }
}
%>
</tbody></table>



Attention

I use a static class which is “synchronized”. You have to be careful about the goulot d’étranglement for the application server with a huge traffic. Personnaly I use this in a production server (intranet ) without any problems.


Downloads

StatsFilter.zip le code Source
StatsFilter.jar la librairie

Be Sociable, Share!