Logging Basics

Grails uses its common configuration mechanism to configure the underlying Log4j log system. To configure logging you must modify the file Config.groovy located in the grails-app/conf directory.

This single Config.groovy file allows you to specify separate logging configurations for development, test, and production environments. Grails processes the Config.groovy and configures Log4j appropriately.

Since 1.1 Grails provides a Log4j DSL, that you can use to configure Log4j an example of which can be seen below:

log4j = {
    error  'org.codehaus.groovy.grails.web.servlet',  //  controllers
	       'org.codehaus.groovy.grails.web.pages' //  GSP

warn 'org.mortbay.log' }

Essentially, each method translates into a log level and you can pass the names of the packages you want to log at that level as arguments to the method.

Some useful loggers include:

The Root Logger

The Root logger is the logger that all other loggers inherit from. You can configure the Root logger using the root method:

root {
    error()
    additivity = true
}

The above example configures the root logger to log messages at the error level and above to the default standard out appender. You can also configure the root logger to log to one or more named appenders:

appenders {
	file name:'file', file:'/var/logs/mylog.log'
}
root {
    debug 'stdout', 'file'
    additivity = true
}

Here the root logger will log to two appenders - the default 'stdout' appender and a 'file' appender.

You can also configure the root logger from the argument passed into the Log4J closure:

log4j = { root ->
    root.level = org.apache.log4j.Level.DEBUG
    …
}
The closure argument "root" is an instance of org.apache.log4j.Logger , so refer to the API documentation for Log4J to find out what properties and methods are available to you.

Custom Appenders

Using the Log4j you can define custom appenders. The following appenders are available by default:

For example to configure a rolling file appender you can do:

log4j = {
	appenders {
		rollingFile name:"myAppender", maxFileSize:1024, file:"/tmp/logs/myApp.log"
	}
}

Each argument passed to the appender maps to a property of underlying Appender class. The example above sets the name, maxFileSize and file properties of the RollingFileAppender class.

If you prefer to simply create the appender programmatically yourself, or you have your own appender implementation then you can simply call the appender method and appender instance:

import org.apache.log4j.*

log4j = { appenders { appender new RollingFileAppender(name:"myAppender", maxFileSize:1024, file:"/tmp/logs/myApp.log") } }

You can then log to a particular appender by passing the name as a key to one of the log level methods from the previous section:

error myAppender:"org.codehaus.groovy.grails.commons"

Custom Layouts

By default the Log4j DSL assumes that you want to use a PatternLayout. However, there are other layouts available including:

You can specify custom patterns to an appender using the layout setting:

log4j = {
	appenders {
        console name:'customAppender', layout:pattern(conversionPattern: '%c{2} %m%n')
    }
}

This also works for the built-in appender "stdout", which logs to the console:

log4j = {
    appenders {
        console name:'stdout', layout:pattern(conversionPattern: '%c{2} %m%n')
    }
}

Full stacktraces

When exceptions occur, there can be an awful lot of noise in the stacktrace from Java and Groovy internals. Grails filters these typically irrelevant details and restricts traces to non-core Grails/Groovy class packages.

When this happens, the full trace is always written to the StackTrace logger. This logs to a file called stacktrace.log - but you can change this in your Config.groovy to do anything you like. For example if you prefer full stack traces to go to standard out you can add this line:

error stdout:"StackTrace"

You can completely disable stacktrace filtering by setting the grails.full.stacktrace VM property to true:

grails -Dgrails.full.stacktrace=true run-app

Logging by Convention

All application artefacts have a dynamically added log property. This includes domain classes, controllers, tag libraries and so on. Below is an example of its usage:

def foo = "bar"
log.debug "The value of foo is $foo"

Logs are named using the convention grails.app.<artefactType>.ClassName. Below is an example of how to configure logs for different Grails artefacts:

log4j = {
	// Set level for all application artefacts
	info "grails.app"
	// Set for a specific controller
	debug "grails.app.controller.YourController"
	// Set for a specific domain class
	debug "grails.app.domain.Book"
	// Set for all taglibs
	info "grails.app.tagLib"

}

The artefacts names are dictated by convention, some of the common ones are listed below: