Spring Tracing
 



Introduction
This Insight article presents the basic and straight forward steps to integrating JXInsight with Spring based applications. One of the key features of the Spring framework is its AOP support which allows users to implement custom aspects, complementing their use of OOP with AOP. The JXInsight Spring trace extension provides a plug-in replacement for the basic performance and debugging interceptors distributed with the Spring libraries. The JXInsight TraceInterceptor (com.jinspired.jxinsight.trace.ext.spring.TraceInterceptor) provides high resolution clock counters, JVM statistics including GC time, CPU time, object allocations, thread blocking and waiting per trace interval as well as call stack inspection and classification and integration into the award winning JXInsight console.

Sample Application
I have chosen the Spring JPetStore sample application for the basis of this article. The following is an extract from readme.txt file within the sample application which is shipped with the Spring Framework distribution.

"The Spring JPetStore is an adapted version of Clinton Begin's JPetStore. It leverages Spring's support for the iBATIS SQL Maps to improve the original JPetStore in terms of internal structure and wiring. On top of a Spring-managed middle tier, it offers two alternative web tier implementations: one using Spring's web MVC plus JSTL, and one using Struts 1.1 plus JSTL."


IMPORTANT NOTE
Before integrating JXInsight the JPetStore application should have already being deployed and tested to ensure that everything is configured, built and running correctly. In this article the database back end used is Hypersonic SQL DB.

Integration Steps

Step 1 - Integrate JXInsight JDBInsight Transaction Analysis. This is an optional step.
Change the jdbc.properties file located in samples/jpetstore/war/WEB-INF.

Before

jdbc.driverClassName=org.hsqldb.jdbcDriver
jdbc.url=jdbc:hsqldb:hsql://localhost:9002
jdbc.username=sa
jdbc.password=

After
jdbc.driverClassName=com.jinspired.jdbinsight.drivers.jdbc1x.Driver
jdbc.url=jdbc:jdbinsight:hsqldb:hsql://localhost:9002
jdbc.username=sa
jdbc.password=


Step
2 - Integrate JXInsight Spring TraceInterceptor
Change the applicationContext.xml file located in samples/jpetstore/war/WEB-INF.

Before
<!-- Transactional proxy for the JPetStore primary business object -->
<bean id="petStore" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
   <property name="transactionManager"><ref bean="transactionManager"/></property>
   <property name="target"><ref local="petStoreTarget"/></property>
   <property name="transactionAttributes">
   <props>
      <prop key="insert*">PROPAGATION_REQUIRED</prop>
      <prop key="update*">PROPAGATION_REQUIRED</prop>
      <prop key="*">PROPAGATION_REQUIRED,readOnly</prop>
      </props>
   </property>
   ...
</bean>

After
<bean id="jxinsight" class="com.jinspired.jxinsight.trace.ext.spring.TraceInterceptor"/>
<!-- Transactional proxy for the JPetStore primary business object -->

<bean id="petStore" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
   <property name="transactionManager"><ref bean="transactionManager"/></property>
   <property name="target"><ref local="petStoreTarget"/></property>
   <property name="transactionAttributes">
   <props>
      <prop key="insert*">PROPAGATION_REQUIRED</prop>
      <prop key="update*">PROPAGATION_REQUIRED</prop>
      <prop key="*">PROPAGATION_REQUIRED,readOnly</prop>
      </props>
   </property>
   <property name="preInterceptors">
      <list>
         <ref bean="jxinsight"/>
      </list>
   </property>
   ...
</bean>


Step 3 - Integrate JXInsight Servlet Trace Extension (ServletFilter)
The following was inserted into the Spring JPetStore web.xml file before the first servlet entry.

<filter>
   <filter-name>jxinsight</filter-name>
   <filter-class>com.jinspired.jdbinsight.trace.ext.servlet.TraceFilter</filter-class>
   <init-param>
      <param-name>trace.identifiers</param-name>
      <param-value>${servlet.protocol},${servlet.method},${servlet.url}</param-value>
   </init-param>
</filter>
<filter-mapping>
   <filter-name>jxinsight</filter-name>
   <url-pattern>/*</url-pattern>
</filter-mapping>


IMPORTANT NOTE
Some web containers support a global web.xml file where the above changes can be inserted and applied to all deployed web applications.


Step 4 - Add JXInsight Spring Trace Extension Library To WEB-INF/lib distribution
If you are rebuilding the JPetStore web archive with the supplied build.xml then insert the following fileset element into the copy task within the build target. The jxinsight-ext-spring.jar must be placed in the WEB-INF/lib directory within the generated war file.

<fileset dir="${jxinsight.root}/lib">
<include name="jxinsight-ext-spring.jar"/>
</fileset>


The ant build scripts can now be executed. Note: It is also possible to apply the previous steps post the building of the web archive by manually updating the web archive itself making sure to add the jxinsight trace extension library into the WEB-INF/lib directory within the file.


Step 5 - Add JXInsight JVMPI Agent, Core Libraries and J2EE/JDBC Extensions to Application Server Classpath

IMPORTANT NOTE
The Borland Enterprise Server platform was used to deploy the web application. The installation steps are similar across most J2EE platforms. Please consult the install guide and the various integration guides for additional platform specific instructions.

There are 3 additional Java libraries which must be added to the application server's classpath. These are jxinsight-core.jar, jxinsight-jdbc-drivers.jar and jxinsight-ext-j2ee.jar. For BES the jxinsight-ext-vbj.jar was also added. To place them on partition's classpath the libraries where placed in the directory:
<BES-INSTALL-ROOT>\var\servers\<HOSTNAME>\partitions\standard\lib\system

The following JVM startup parameter was added to the partitions server configuration file. The v=t is a required Borland VisiBroker flag.
vmparam -Xrunjdbinsight:v=t


Step 6 - Startup the Database Server, Application Server and Browser

The HSQLDB server database engine process should be started configured with the JPetStore DB files. The Borland Application should be restarted after deploying the jpetstore.war file. Navigate to the urlhttp://localhost:8080/jpetstore/index.html. The following front page should now be displayed.



Perform some operations within the application to warm up the application creating traces and transaction paths.

IMPORTANT NOTE
The JXInsight embedded profile server will intially incurr a larger overhead than normal (5%) during its JVM model building phase. After most entry points have been visited the JXInsight server will utilize its internal fast access cached data structures.



Step
7- The JXInsight Console
Start the JXInsight Management Console. Mount a JXInsight server (monitored JVM process) via the console menu command sequence: File->Mount Server. Enter the host name (localhost) and port number (default 1515). The console should automatically connect and retrieve the metric snapshot. Switch the analysis mode to Profile. The Transactions perspective is activated within the console's view system. The blue icon in the callstack column represents a web bean (Servlets/JSP). The green (olive) icon in the trace stack column represents a Spring bean trace.



Switching to the Traces perspective presents the following analysis view.



In both tables views time values are reported in microseconds for clock time, cpu time, thread monitoring waiting/blocking, and GC. Object allocations are reported in byte sizes (GB, MB, KB, Bytes).


Advanced Configuration
JXInsight's Spring Trace extension can be configured to separate a single trace event into multiple trace stack entries. By default the extension creates the following trace stack entries, ${type}=value, for each traced method invocations.

${spring.bean.classname}=<classname without package>
${spring.bean.operation}=<method.name>

This can be changed globally via the system property with trace identifiers delimited by a comma:
-Djxinsight.server.tracer.ext.spring.bean.trace.identifiers=${spring.bean.classname},${spring.bean.operation}

${spring.bean.codesource}
${spring.bean.package}
${spring.bean.classname}
${spring.bean.fullclassname}
${spring.bean.operation}
${spring.bean.method}
${spring.bean.signature}
${trace.timestamp}

The TraceInterceptor bean allows supports instance level configuration via the Java bean property "identifiers". The property takes a string with valid trace identifiers delimited by a comma.


William Louth, JXInsight's Product Architect