Saturday, December 29, 2012

How to monitor performance of portlets

There is a very common requirement where we have a need that how to monitor performance of portlets specially when the portlets are misbehaving.
We can use the concept of Global Filters to create a filter that will monitor all your portlets (render, resource, action and Event phase) and write a message in the log if one of the method takes more than the threshold time.

Below is the code of Performance Filter. Here we have created a java class name as PortletPerformanceFilter.java

package com.company.performance.filter;

import java.io.IOException;
import javax.portlet.PortletException;
import javax.portlet.PortletRequest;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;
import javax.portlet.filter.FilterChain;
import javax.portlet.filter.FilterConfig;
import javax.portlet.filter.RenderFilter;

public class PortletPerformanceFilter implements RenderFilter {
            public void destroy() {
System.out.println("Inside PortletPerformanceFilter.destroy()");
            }
public void init(FilterConfig arg0) throws PortletException {
System.out.println("Inside PortletPerformanceFilter.init()");
            }
public void doFilter(RenderRequest request, RenderResponse response,
                                    FilterChain filterChain) throws IOException, PortletException {
                        try{
                        if (isPerformanceFilter(request)) {
System.out.println("Entering PortletPerformanceFilter.doFilter()");
            long beginTime = System.currentTimeMillis();
            filterChain.doFilter(request, response);
long endTime = System.currentTimeMillis();
            long executionTime = (endTime - beginTime) ;
System.out.println("Portlet Window ID " + request.getWindowID()
                                                            + " Time to execute render = "
                                                            + executionTime + " ms");
System.out.println("Exiting PortletPerformanceFilter.doFilter()");
                        } else {
// if not in maintenance, just call the normal chain
filterChain.doFilter(request, response);
                        }
                        }
            catch(Exception e){
System.err.println("PortletPerformanceFilter Error"+ e.getMessage());
            }
}
/*
 * Checks if the portlet addressed in the request has to be checked for  PerformanceFilter
 */
private boolean isPerformanceFilter(PortletRequest request) {
            boolean isPerformanceFilter = false;
isPerformanceFilter = Boolean.valueOf(request.getPreferences(). getValue ("PERFORMANCECHECK", "false")).booleanValue();
            return isPerformanceFilter;
            }
}

In the doFilter() method we are taking the time before and after forwarded control up the chain and using that time to calculate execution time which we are printing.


To use global portlet filters, add the following code to the root folder or in the WEB-INF directory of your web application and name it plugin.xml file:


<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.0"?>
<plugin id="com.brocade.webportal.performance.filter" name="WS_Server" provider-name="IBM" version="2.0.0">
<extension point="com.ibm.ws.portletcontainer.portlet-filter-config">
            <portlet-filter-config class-name="com.brocade.webportal.performance.filter.PortletPerformanceFilter" order="100">
<description> Portlet Performance Filter, order = 101 </description>
            <lifecycle>RENDER_PHASE</lifecycle>
            </portlet-filter-config>
    </extension>
</plugin>

The above implementation is for RenderFilter interface, for example, which has been added as  <lifecycle>RENDER_PHASE</lifecycle> code in plugin.xml. This addition is analogous to the other filter interfaces. The following values are valid for the <lifecycle> parameter:
  • RESOURCE_PHASE
  • EVENT_PHASE
  • ACTION_PHASE
Once the PortletPerformanceFilter is developed we have to copy it in the shared library so that it can be accessed by portal across application.

These global filters apply to all portlets that are running within the portlet container, including both plain portlets and console modules.

The portlet in which we want to check the performance, we need to set portlet preferences as :PERFORMANCECHECK and its value should be true
 

No comments:

Post a Comment