Configuring Logging
Grails uses its common Config mechanism to configure Log4j since 0.6. If you want to find out how to configure logging in 0.1 to 0.5.6 see previous revisions on this page. To configure logging you must modify the file Config.groovy located in directory grails-app/conf. This single Config.groovy file allows you to specify separate logging configurations for development, test, and production. Grails processes the Config.groovy file and generates the appropriate log4j.properties file in directory web-app/WEB-INF/classes.
| Who stole my stacktrace? Since Grails 1.0, stacktraces are summarized to exclude what is usually unnecessary detail to help you see the true cause of the problem. However the full trace is never lost, it is sent to a separate "StackTrace" log which you configure in Config.groovy. By default this will write to a file so that it does not clutter your stdout. You can edit this behaviour in any way you like. |
You can configure Log4j loggers as follows:
log4j {
appender.stdout = "org.apache.log4j.ConsoleAppender"
appender.'stdout.layout'="org.apache.log4j.PatternLayout"
rootLogger="error,stdout"
logger {
grails="info,stdout"
org {
grails.spring="info,stdout"
codehaus.groovy.grails.web="info,stdout"
codehaus.groovy.grails.commons="info,stdout"
...
}
}
Some useful loggers include:
- org.codehaus.groovy.grails.commons - Core artifact information such as class loading etc.
- org.codehaus.groovy.grails.web - Grails web request processing
- org.codehaus.groovy.grails.web.mapping - URL mapping debugging
- org.codehaus.groovy.grails.plugins - Log plugin activity
- org.springframework - See what Spring is doing
- org.hibernate - See what Hibernate is doing
- StackTrace - full stacktraces when stacktrace filtering is on (default is ON)
Stacktrace logs (Since 1.0)
When exceptions occur, there is usually 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. By default with new 1.0 applications, this logs to a file called stacktrace.log - but you can change this in your Config.groovy to do anything you like, for example send it to stdout you just change the logger entry in Config.groovy to StackTrace="error, stdout"
You can completely disable stacktrace filtering by setting the grails.full.stacktrace VM property to "true" i.e. add the -Dgrails.full.stacktrace=true option to your application startup script.
Artifact logs (Since 0.5)
All application artifacts have a dynamically added "log" property. This includes Domain classes, Controllers, Taglibs, Jobs, Services, Bootstraps, Datasources etc.
Logs are named using the convention "grails.app.<artifactType>.ClassName". Examples from a generated log4j.properties file are shown below:
# Set level for all application artifacts log4j.logger.grails.app="info, stdout" # Set for a specific controller log4j.logger.grails.app.controller.YourController="debug, stdout" # Set for a specific domain class log4j.logger.grails.app.domain.Book="debug, stdout" # Set for a specific taglib log4j.logger.grails.app.tagLib.FancyAjax="debug, stdout" # Set for all taglibs log4j.logger.grails.app.tagLib="info, stdout"
The artifact type IDs come from the registered artifact handlers. At the time of writing, out of the box these are:
- bootstrap
- dataSource
- tagLib
- service
- controller
- task
- domain
Environment specific artifact logs
Environment specific configuration is placed in the Config.groovy file below the initial log4j scope as shown in the example below:
log4j {
...
logger {
grails="error,stdout"
org {
codehaus.groovy.grails.web.servlet="info,stdout" // controllers
...
}
}
}
environments {
development {
log4j {
logger {
grails.'app.controller.YourController'="debug,stdout"
grails.'app.controller.YourOtherController'="off,stdout"
grails.'app.controller'="info,stdout"
grails.'app.domain.Book'="debug,stdout"
grails.'app.domain'="info,stdout"
grails.app="error,stdout"
}
}
}
production {
log4j {
logger {
...
grails.'app.controller'="info,stdout"
grails.app="error,stdout"
}
}
}
test {
log4j {
logger {
...
}
}
}
}
A couple things to keep in mind while modifying Config.groovy:
1) Unlike the flat format used by log4j, the Grails config format is hierarchical, so if you write:
grails.app.controller.YourController="debug,stdout" grails="info,stdout"
You're actually overriding the first setting with the second. To get around this you have to quote the first:
grails.'app.controller.YourController'="debug,stdout" grails="info,stdout"
2) If you're not using the 'quote' format shown above you must always define children before parents in the Config.groovy file. For example, putting a parent before a child as shown below will result in an error:
grails.app="info,stdout" grails.app.controller="debug,stdout"
Reversing the lines will eliminate the error (but the definition of grails.app will override the definition of grails.app.controller):
grails.app.controller="debug,stdout" grails.app="info,stdout"
Log4j Hibernate Output
To log all SQL queries and all the stuff hibernate does, add the line
log4j.logger.org.hibernate=debug, stdout
Sample Config with File Logging
This sample config does logging to file as well as stdout
// log4j configuration log4j { appender.stdout = "org.apache.log4j.ConsoleAppender" appender.'stdout.layout'="org.apache.log4j.PatternLayout" appender.'stdout.layout.ConversionPattern'='[%r] %c{2} %m%n' appender.logfile = "org.apache.log4j.DailyRollingFileAppender " appender.'logfile.File' = "yourlogfile.log" appender.'logfile.layout' = "org.apache.log4j.PatternLayout" appender.'logfile.layout.ConversionPattern' = '%d{[ dd.MM.yy HH:mm:ss.SSS]} [%t] %-5p %c %x - %m%n' rootLogger="error,stdout" logger { grails="info,stdout,logfile" org { codehaus.groovy.grails.web.servlet= "info,stdout,logfile" // controllers codehaus.groovy.grails.web.pages="info,stdout,logfile" // GSP codehaus.groovy.grails.web.sitemesh="info,stdout,logfile" // layouts codehaus.groovy.grails."web.mapping.filter"="info,stdout,logfile" // URL mapping codehaus.groovy.grails."web.mapping"="info,stdout,logfile" // URL mapping codehaus.groovy.grails.commons="info,stdout,logfile" // core / classloading codehaus.groovy.grails.plugins="info,stdout,logfile" // plugins codehaus.groovy.grails.orm.hibernate= "info,stdout,logfile" // hibernate integration springframework="off,stdout,logfile" hibernate="off,stdout,logfile" org.codehaus.groovy.grails.plugins.acegi= "all,stdout,logfile" } } }