Usage Tracking with Grails

When a web application goes live, it can be very useful to keep track of what people are doing with your application.
It is important to discover the “hot spots” of your application which you should optimize in terms of usability and performance.
Besides that, it could be vary handy to track all actions a single user makes in one session, so it will get easier to find out whats going wrong when a problem is reported.

This blog post will show you how to

  • Log the user’s sessionID (or username/user id) with every log message
  • Log every access to a controller action

Grails makes it very easy to implement this.

Log the user’s sessionID (or username/user id) with every log message

In my last blog post Logging additional information like SessionID in every Log4j message I explained the concept of the Mapped Diagnostic Context (MDC) – a thread-local key-value store that can be accessed from the Log4j conversion pattern. We will use the MDC to log the user’s sessionID or any user or session related information.

Modify your Log4j config in Config.groovy and put a placeholder for the sessionID into your conversion pattern:

log4j = {
	appenders {
		console name: 'stdout', layout: pattern(conversionPattern: '[%d{HH:mm:ss}] %X{sessionId} %p %c{1} - %m%n')
		...

Now we have to fill the sessionId variable for each request. Create a new filter class named LoggingFilters in grails-app/conf:

import org.springframework.web.context.request.RequestContextHolder
import org.slf4j.MDC

class LoggingFilters {
    def filters = {
        all(controller:'*', action:'*') {
            before = {
				String sessionId = RequestContextHolder.getRequestAttributes()?.getSessionId()
				if(sessionId){
					MDC.put('sessionId', sessionId)
				}
            }
            after = {
            }
            afterView = {
				MDC.remove('sessionId')
            }
        }
    }
}

This filter will get invoked before every controller action, extract the session id from the request and put it into the MDC. After every view rendering, the sessionId will be removed from the MDC (clean it up).

 

That’s it. From now on, every log message will include the session id, so you are able to see which log messages belong to a user session. It is a good practice to include the session id only when logging to a file, and don’t log it to the console to avoid an information overload on the developer’s screen.

Log every access to a controller action

Now we are going to log every access to a controller action. This will allow you to see what pages your users access. Because you can group these log messages by sessionIds (see above), you can see the path a user follows while using your web app.

Create another filter class named UsageTrackingFilters in grails-app/conf:

import org.apache.commons.logging.Log
import org.apache.commons.logging.LogFactory

class UsageTrackingFilters {

	private static final Log LOG = LogFactory.getLog('usagetracking')

	def filters = {
		all(controller:'*', action:'*') {
			before = {
				LOG.info("Access to $controllerName/$actionName")
			}
			after = {
			}
			afterView = {
			}
		}
	}
}

We are using a dedicated logging category usagetracking so you could separate these log statements from your log file and log the usage tracking messages to a separate logfile.

 

That’s all that is needed to implement usage tracking with Grails. You are now able to see what your users are doing with your application.

Short URL for this post: http://wp.me/p4nxik-jY
This entry was posted in Groovy and Grails, Java Web Frameworks and tagged , , , . Bookmark the permalink.