- Add jamon.jar to the application classpath
- Use JAMon's datasource proxy to monitor SQL
- Implement the JAMonServletFilter to monitor page hits
- Leverage Spring AOP via Spring's JamonPerformanceMonitorInterceptor class to monitor services
- Add a Spring filter to monitor Grails controllers
Create a package structure under grails-app/conf. I used org/grails/plugins/filters. Create a file named JamonFilters and add the following code:
package org.grails.plugins.filters
import com.jamonapi.MonitorFactory
import com.jamonapi.Monitor
import org.codehaus.groovy.grails.commons.ConfigurationHolder
/**
* @author eric weimer
*/
class JamonFilters {
Monitor monitor, viewMonitor, previewMonitor
def skipControllers = (ConfigurationHolder.config.jamon.controllersToExclude)? ConfigurationHolder.config.jamon.controllersToExclude: []
def filters = {
monitorController(controller: "*", action: "*") {
before = {
if (!(controllerName in skipControllers)) {
def monName = "Controller.${controllerName}.${actionName}"
monitor = MonitorFactory.start("${monName}")
previewMonitor = MonitorFactory.start("${monName}.noview")
}
true
}
after = {
if (previewMonitor) {
previewMonitor.stop()
def monName = "Controller.${controllerName}.${actionName}.view"
viewMonitor = MonitorFactory.start("${monName}")
}
true
}
afterView = {
if (monitor) monitor.stop()
if (viewMonitor) viewMonitor.stop()
true
}
}
}
}
This code calls JAMon methods to start and stop timings. Note the variable skipControllers. This allows users of the plugin to easily define a list of controllers NOT to monitor by adding the variable
jamon.controllersToExclude to groovy.config.
This is all you need to do! Grails will add this filter to the application when you install the plugin.
To allow users to provide additional customizations to the plugin, we document some configuration settings they can set, and then access those settings in our plugin. For example, in the application's Config.groovy class, let's allow users to specify the following:
jamon.monitorControllers = true
jamon.monitorServices = true
jamon.servicesToExclude = ['consoleService']
jamon.controllersToExclude = []
jamon.additionalBeans = ['com.eweimer.terrapin.util.MediaAccess','com.eweimer.terrapin.util.Key']
These settings will allow users to turn off monitoring for Controllers or Services, and specify services NOT to monitor as well as additional Spring beans classes to include.
To access these values in our JamonGrailsPlugin, we'll import:
import org.codehaus.groovy.grails.commons.ConfigurationHolder
To perform a safe test on a boolean value we can use the following code to default to true when the user does not specify a value:
def skipServices = application.config.jamon.servicesToExclude ?: []
Put together, the code now looks like this:
def monBeanNames = []
def skipServices = application.config.jamon.servicesToExclude ?: []
if (application.config.jamon.monitorServices ?: true) {
monBeanNames = application.serviceClasses.collect{ it.shortName[0].toLowerCase() + it.shortName[1..-1] }
monBeanNames -= skipServices
}
if (application.config.jamon.additionalBeans) {
monBeanNames += application.config.jamon.additionalBeans
}
By using this logic we can allow users to easily customize the behavior of our jamon plugin.
The final step is to deploy your plugin. Type "grails package-plugin" in the root of your plugin project and Grails will create a .zip file. Then go to your Grails application and type "grails install-plugin path-to-your-zip-file", and you are ready to go.
Deploy the jamon.war that comes with the JAMon distribution to your web server then point your browser to /jamon/menu.jsp to view the results. Viola!
I hope you enjoyed this series. I'll add one more installment about testing your plugin when I have the chance. Meanwhile, have fun!