Grails comes complete with logging out-of-the-box. However, if a Grails application is being deployed to a production servlet container, it may be advisable or even required for Grails to step aside and let the server admins do their jobs :-)
Update: There’s a follow up that includes full source and a ready-to-deploy war. See How to Deploy a Grails Application to JBoss 5.
You need not avoid the loggers injected by Grails in order to use the native logging provided by servlet containers (e.g. Tomcat, GlassFish, JBoss). Grails loggers (always have implemented and now still) implement org.apache.commons.log.Log through jcl-over-slf4j delegating to some slf4j implementation adapter. You’re free to choose which logging system will ultimately perform the “real” logging. This is what we do:
- Use the slf4j Implementation adapter that delegates to the native logging supplied by the web server container, e.g. slf4j-log4j12 for JBoss or slf4j-jdk14 for GlassFish / standard Tomcat 6. One (and only one) of those must be packaged within the war.
- Remove any logging implementation from our war (e.g. log4j), as it will be supplied by the servlet container (e.g. Log4j with JBoss or Java-logging with GlassFish / standard Tomcat 6.x).
- Disable Grails logging configurator.
- Use whatever means the web server container offers to configure its logging.
Step 2 can be implemented within grails-app/BuildConfig.groovy similar to:
grails.war.resources = {stagingDir -> def toRemove = [ "$stagingDir/WEB-INF/lib/log4j-1.2.14.jar", // Logging -> native GlassFish/Tomcat/JBoss "$stagingDir/WEB-INF/lib/log4j-1.2.15.jar", // " "$stagingDir/WEB-INF/classes/log4j.properties", // " "$stagingDir/WEB-INF/lib/slf4j-log4j12-1.5.6.jar", // " "$stagingDir/WEB-INF/lib/slf4j-log4j12-1.5.8.jar", // " ].each { delete(file: it) } }
Step 3 can be achieved by altering the web.xml, either verbatim or by means of a grails-app/scripts/_Events.groovy which might looks similar to:
import groovy.xml.StreamingMarkupBuilder eventWebXmlEnd = {String tmpfile -> def root = new XmlSlurper().parse(webXmlFile) // remove some log4j stuff def log4j = root.listener.findAll {node -> node.'listener-class'.text() == 'org.codehaus.groovy.grails.web.util.Log4jConfigListener' } log4j.replaceNode {} def log4jFile = root.'context-param'.findAll {node -> node.'param-name'.text() == 'log4jConfigLocation' } log4jFile.replaceNode {} webXmlFile.text = new StreamingMarkupBuilder().bind { mkp.declareNamespace("": "http://java.sun.com/xml/ns/j2ee") mkp.yield(root) } }
