09 February 2012

Get in control with Spring Insight!

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.

tc Server Developer Edition 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.

5 comments:

  1. Nice one, we have created a plugin for the axon framework as well. Will have a look at your implementation on our hippo projects

    ReplyDelete
  2. Hi Jeroen / Jettro,
    I'm from the Spring Insight team. Nice to see people writing plugins for Insight.
    If you'd like we can add your plugins to the insight plugins opensource project.

    ReplyDelete
  3. Hi Tal,

    thank you for visiting and for this great offer. I'll see if I can polish the plugin a bit more and will send a pull request when I'm done if that's OK with you?

    Cheers,

    Jeroen

    ReplyDelete
  4. Hey Jeroen,
    Do you know how I can integrate Spring Insight with plain vanila tomcat 6.x ?
    I know that Spring Insight talks about its support for tomcat but I am not able to find a single place of documentation of how I can do it?

    If you could point me to some page that talks abouot it or can provide me some pointers that would be really helpful.

    Cheers!
    Anuj

    ReplyDelete
    Replies
    1. Hi Anuj.

      I looked at this as well, but currently (unless it has changes over the last months) this is not possible. They make use of some additional features of the VMware vFabric TM tc Server (which is tomcat on steriods). The additional features (like classloading, etc) of the vFabric server makes Spring insight such a nice tool.

      Sorry I cannot help.

      Jeroen

      Delete