Ever wondered what your application was doing? Why that specific page was so slow? I've asked myself this question numerous times and always had to change some log level or attach a profiler to get actual feedback on what was going on inside my application.

The other day while commuting from home to work, I discovered the Spring Insight project. From what I've seen so far Spring Insight is a set of inspections (plugins) which are visually displayed in a web application. To get an idea of what Spring Insight can do for you, be sure to check out the introduction screencast.

By default Spring Insight comes with a default set of plugins/inspections for different kinds of frameworks/libraries like:

  • Spring Web, Spring core
  • JDBC
  • Servlets
  • Hibernate
  • Grails

There are more plugins available and it's even quite easy to create some of your own and that's what the rest of this post is about.

Writing your own Spring Insight plugin

Working with Hippo CMS driven web applications every day I had the idea of creating a Spring Insight plugin for the Hippo Site Toolkit (HST in short). The HST consists of a set of components that interact with the Hippo content repository. During a single request multiple components can be called and for each component there are multiple processing phases. So my initial idea for the Spring Insight plugin was to show:

  1. The amount of time taken for each processing phase of an HST component
  2. The time it takes to perform an HstQuery to the repository

Because the default Spring Insight plugins are open source I was able to write my first plugin in about 30 minutes or so. A large part of those 30 minutes were taken up with learning AspectsJ, because I'd never used that before.

Getting started

For this post we will now focus on creating an inspection on performing HST queries. From the Insight web application view I would like to see the information of an HstQuery and time it took to perform the actual query. With AspectJ you can pick a join point and inspect for instance the execution of that join point. In our case I would like to inspect the HstQuery.execute() method. By putting the join point on the HstQuery interface, we've made sure that any object extending the HstQuery will be able to represent it's data within the Insight web application.

Let's first take a look at the what such an inspection looks like.

package com.jeroenreijn.insight.hst;
import com.springsource.insight.collection.AbstractOperationCollectionAspect;
import com.springsource.insight.intercept.operation.Operation;
import com.springsource.insight.intercept.operation.OperationType;

import org.aspectj.lang.JoinPoint;
import org.hippoecm.hst.content.beans.query.HstQuery;
import org.hippoecm.hst.content.beans.query.HstQueryResult;
import org.hippoecm.hst.content.beans.query.exceptions.QueryException;

/**
 * Aspect for collecting HstQuery executions.
 */
public aspect HstQueryOperationAspect extends AbstractOperationCollectionAspect {

  private static final OperationType TYPE = OperationType.valueOf("query_execute");
  public pointcut collectionPoint(): execution(HstQueryResult HstQuery.execute());

  public Operation createOperation(JoinPoint jp) {
    HstQuery query = (HstQuery) jp.getTarget();
    Operation op = new Operation().type(TYPE).label("HstQuery");
    op.sourceCodeLocation(getSourceCodeLocation(jp));
    try {
      op.put("query", query.getQueryAsString(false));
      op.put("limit", query.getLimit());
      op.put("offset", query.getOffset());
    } catch (QueryException e) {
      // ignore for now
    }
    return op;
  }
}

The more important part of the above collection aspect is the collectionPoint poincut, where we define what kind of operation we would like to collect information from. In this case we define an inspection on the HstQuery.execute() method. Next to the collection point you will also see the createOperation() method. which allows you to collect certain information from the current state of the collection point. In the above code snippet we collect the actually HstQuery object and get some information from it like the actual JCR XPath query, the limit set on the query and the offset. That's all for the information collection part of our plugin. Now that we've created the aspect for the HstQuery, let's create a view for this inspection. You can create a freemarker template for each inspection if you want. For the HstQuery I've created the following template.

<#ftl strip_whitespace=true>
<#import "/insight-1.0.ftl" as insight />
<@insight.group label="HST Query">
  <@insight.entry name="Query" value=operation.query />
  <@insight.entry name="Limit" value=operation.limit />
  <@insight.entry name="Offset" value=operation.offset/>
</@insight.group>

In the above template we define the values that we've put as attributes on our Operation object. All we have to do now is wire the operation and the view together inside the plugin configuration.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:insight="http://www.springframework.org/schema/insight-idk"
   xsi:schemaLocation="http://www.springframework.org/schema/beans
   http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
   http://www.springframework.org/schema/insight-idk
   http://www.springframework.org/schema/insight-idk/insight-idk-1.0.xsd">

   <insight:plugin name="hst" version="${project.version}" publisher="Jeroen Reijn" />
   <insight:operation-view operation="query_execute" template="com/jeroenreijn/insight/hst/query.ftl" />
   <insight:operation-group group="Hippo" operation="query_execute" />
</beans>

So now that we've finished our plugin, we package it and drop it inside the collection-plugins folder of our Spring Insight instance. Next we fire up the VMware vFabric TM tc Server and do some requests on the web application that we would like to get some information from. Once that's done switch the URL in the browser to '/insight' and there is the information collected by Spring Insight. The image below show exactly the information that we tried to show.

In this example request you can see from the top of the call stack, the chain of filters that the request went through and all of the HST components. For each component you can now see the class, the window name (as you can also see in the CMS console) and the render path ( the JSP or Freemarker template) used for rendering the information of the component. You can also expand an HST component when it contains an HstQuery. The advantage of having such a plugin might help us identify some slow pages that might have slow JCR queries or components that do extensive (unnecessary) processing.

Summary

Spring Insight is a very interesting project. Doing a quick scan for troublesome code is relatively fast, but can for now only be done with the VMware vFabric TM tc Server, so you cannot run it in your personal preferred application container like Tomcat, Jetty or JBoss. I've personally added Spring Insight to my default set of tools for figuring out performance issues when I need to do a review of a project.

All of the above code and how to install this HST Spring Insight plugin can be found on the plugin project page on Github.