Quantcast
Channel: Blog » grails
Viewing all articles
Browse latest Browse all 10

Grails – Multiple Log4j Configurations

$
0
0

This is a quick tip that I found very useful and – to my knowledge – is not part of the Grails documentation by now. So let’s spread the word :-)

In one of my Grails projects, we use external configuration files to apply customer specific settings. We have a custom ConfigurationLoader that is used to locate customer-specific configuration files based on the current environment (VM arguments, *.properties file and such). The configuration loader returns a list of additional configuration files which is handed over to grails.config.locations [0]

// ConfigurationLoader retrieves customConfigLocations, being an ArrayList<String>

grails.config.locations = customConfigLocations

So far so good. Lately we had the requirement to specify customer-specific Log4J log levels, as various components needed a more fine-grained logging level. In Grails versions prior to Grails 2.0 we could have only satisfied this requirement by completely overriding the log4j variable from Config.groovy in the custom configuration file.


// log4j configuration
log4j = {

    error  'org.codehaus.groovy.grails.web.servlet',  //  controllers
           'org.codehaus.groovy.grails.web.pages', //  GSP
           'org.codehaus.groovy.grails.web.sitemesh', //  layouts
           'org.codehaus.groovy.grails.web.mapping.filter', // URL mapping
           'org.codehaus.groovy.grails.web.mapping', // URL mapping
           'org.codehaus.groovy.grails.commons', // core / classloading
           'org.codehaus.groovy.grails.plugins', // plugins
           'org.codehaus.groovy.grails.orm.hibernate', // hibernate integration
           'org.springframework',
           'org.hibernate',
           'net.sf.ehcache.hibernate'
}

Luckily, Ian Roberts introduced a far more elegant way to extend the log4j configuration.

Using a map of closures

As of Grails 2.0, there is a way to extend the Log4J configuration rather than replacing it. The way to go is to use a log4j variable of type Map<String, Closure> instead of Closure.


// main configuration
log4j.main = {
   // ...
}

// external (customer-specific) configuration
log4j.external = {
  // common configuration
}

environments {
  development {
    log4j.env = {
      // environment-specific config
    }
  }
  production {
    log4j.env = {
      // environment-specific config
    }
  }
}

As you can see in the code listing above, log4j is now treated as map, rather than a single value object. As groovy.util.ConfigObject [1] extends LinkedHashMap, the log4j entries will be called in the defined order and the resulting configuration entries will be merged. With this patch, we were able to add customer-specific log levels to our external configuration files.

If you want to have a look at the corresponding patch introducing this feature, check out [2].

[0] Grails Documentation – Externalized configuration
[1] groovy.util.ConfigObject
[2] Jira GRAILS-7314


Viewing all articles
Browse latest Browse all 10

Latest Images

Trending Articles





Latest Images