Using JAMON for monitoring REST service

JAMON is very nice and powerful performance monitoring tool. You can use it to monitor performance of java program. I wanted to monitor performance of a REST service so i built this generic purpose filter that any one can use. Once installed it generates performance stats like this. You can download the sample code from here
I followed these steps to create the filter
  1. First download the JAMON binaries from AMON home page
  2. Expand the binaries and copy the jamon.jar file in the shared library of your application server
  3. Next install jamon.war which is web application that ships with jamon binary and provides a UI to look at the stats. The screen shot that you see is taken using jamon.war
  4. I already have a REST service that exposes a CONTACT table as a resource, it provides GET, POST, PUT and DELETE operations on the Contact resource
  5. For the JAMON monitoring part i did create this simple filter
    
    package com.webspherenotes.performance.filter;
    
    import java.io.IOException;
    import javax.servlet.DispatcherType;
    import javax.servlet.Filter;
    import javax.servlet.FilterChain;
    import javax.servlet.FilterConfig;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    import javax.servlet.annotation.WebFilter;
    import javax.servlet.http.HttpServletRequest;
    
    import com.jamonapi.Monitor;
    import com.jamonapi.MonitorFactory;
    
    /**
     * Servlet Filter implementation class RESTServiceJAMONFilter
     */
    @WebFilter(dispatcherTypes = {DispatcherType.REQUEST }
              , urlPatterns = { "/*" })
    public class RESTServiceJAMONFilter implements Filter {
    
        public RESTServiceJAMONFilter() {
            // TODO Auto-generated constructor stub
        }
    
      public void destroy() {
        // TODO Auto-generated method stub
      }
    
      /**
       * @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
       */
      public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 
      throws IOException, ServletException {
    
        HttpServletRequest httpServletRequest= (HttpServletRequest)request;
        Monitor monitor = MonitorFactory.start(RESTCacheKeyBuilder.buildCacheKey(httpServletRequest));
        chain.doFilter(request, response);
        monitor.stop();
      }
    
      public void init(FilterConfig fConfig) throws ServletException {
        // TODO Auto-generated method stub
      }
    
    }
    
    Inside the filter i start a monitor before passing control up the filter chain and i stop the JAMON monitor once the request is completed, that's all that you have to do to create and record JAMON monitor. You might notice that while starting filter i am calling RESTCacheKeyBuilder.buildCacheKey(httpServletRequest) , this class takes care of creating the monitor key Ex.GET - /JAMONRESTService/rest/contact/xxx is the key that gets created when you call the service by invoking http://localhost:9080/JAMONRESTService/rest/contact/21 url
  6. This is how my key builder looks like
    
    package com.webspherenotes.performance.filter;
    
    import javax.servlet.http.HttpServletRequest;
    
    public class RESTCacheKeyBuilder {
      
      public static String buildCacheKey(HttpServletRequest request){
        StringBuilder cacheKeyBuilder = new StringBuilder();
        cacheKeyBuilder.append(request.getMethod());
        cacheKeyBuilder.append(" - ");
        cacheKeyBuilder.append(request.getContextPath());
        cacheKeyBuilder.append(request.getServletPath());
        cacheKeyBuilder.append(request.getPathInfo());
        String cacheKey = cacheKeyBuilder.toString();
        System.out.println("Cache Key " + cacheKey);
        cacheKey = cacheKey.replaceAll("[0-9]+", "xxx");
        System.out.println("After replacing digits " + cacheKey);
        return cacheKey;
      }
    }
    
    Its very simple, all it does is adds the HTTP method name for the call and the URL for the call, i am replacing all the numbers with xxx. So that the calls for same resource generates same key. Ex. /JAMONRESTService/rest/contact/xxx key would get generated for http://localhost:9080/JAMONRESTService/rest/contact/22 http://localhost:9080/JAMONRESTService/rest/contact/2 http://localhost:9080/JAMONRESTService/rest/contact/210 and as a result i can see how is my GET call on CONTACT resource doing

2 comments:

Robert Morschel said...

I really like Jamon. We did something similar for our REST services, allowing us to measure per-account api usage.

Robert
http://soaprobe.blogspot.co.uk/2012/10/soa-service-management-rest-api.html

Anonymous said...

Hello, im trying to do this, but jamon isnt showing my data, do yo do something else???