Logback Plugin

  • Tags : /
  • Latest : 0.3.1
  • Last Updated: 06 May 2013
  • Grails version : 2.0 > *
0 vote
Dependency :
compile ":logback:0.3.1"

Documentation Source Issues

Summary

Replaces Log4j with Logback for logging

Description

This plugin provides the same logging support as the standard Log4j plugin, but using Logback instead.

The plugin is packaged as a binary plugin, so the usual approaches (i.e. using install-plugin or putting the dependency in the plugins block in BuildConfig.groovy) won't work. Instead you add a dependency in the dependencies section like you do for JAR files:

dependencies {
   compile 'org.grails.plugins:logback:0.3.1'
}

You also need to make one other change. By default Grails ships with the Log4j plugin and the eviction process isn't working, so you need to exclude it from the inherits('global') block, e.g.

inherits('global') {
   excludes 'grails-plugin-log4j', 'log4j'
}

There's one final step - be sure to run grails clean after adding the plugin to BuildConfig.groovy. This is needed because the Log4j plugin uses an AST transformation to add a log field to your artifacts, and you need to recompile everything so this plugin's AST transformation adds a log field that uses a Logback logger instead.

Configuration DSL

The DSL for this plugin is very similar to the one for Log4j. Converting should only require a few steps. For starters, change log4j = { to logback = { , e.g.

logback = {

info 'org.codehaus.groovy.grails', 'org.springframework', 'org.hibernate', 'net.sf.ehcache.hibernate' }

As you can see, defining logger levels is the same as for Log4j. One difference is that there is no "fatal" level in Logback, so although you can use that in the DSL it will be mapped to the "error" level.

You define appenders the same way, inside a appenders block. Layouts are supported in Logback but are mostly deprecated in favor of Encoders, so only Encoders are supported in the DSL. The DSL supports the same four encoders as the Log4j DSLs Layouts, i.e. 'xml', 'html', 'simple', and 'pattern'. 'pattern' is the default and uses a syntax that is very similar to Log4j's, with a few differences. See the syntax documentation for more information.

The DSL also supports the same Appenders as the Log4j DSL, i.e. 'jdbc', 'null', 'console', 'file', and 'rollingFile'.

Here's an example of a more complex configuration. It overrides the default console appender to change the layout pattern (note that the property is pattern and not conversionPattern as in Log4j), adds a FileAppender , and attaches the appender to the grails.app package and sub-packages. In addition the Root logger is updated to use the 'warn' level, and to have both the console ('stdout') and 'mylog' appenders:

logback = {

appenders { console name: 'stdout', encoder: pattern(pattern: '%c{2} %m%n') file name: 'mylog', file: '/tmp/my.log' }

info 'org.codehaus.groovy.grails', 'org.springframework', 'org.hibernate', 'net.sf.ehcache.hibernate'

info mylog: 'grails.app'

root { warn 'stdout', 'mylog' } }

RollingFileAppender

This example configures a rolling file appender, which rolls daily or when the size becomes larger than 10MB. In addition Logback will configure GZipping the rolled logs since the file pattern ends in '.gz' (it will Zip if it ends in '.zip'):

import ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy
import ch.qos.logback.core.rolling.FixedWindowRollingPolicy

logback = { appenders { rollingFile name: 'myAppender', file: '/tmp/rolling.log', encoder: pattern(pattern: '%-4relative [%thread] %-5level %logger{35} - %msg%n'), triggeringPolicy: new SizeBasedTriggeringPolicy(maxFileSize: 10*1024*1024), rollingPolicy: new FixedWindowRollingPolicy(fileNamePattern: '/tmp/rolling.%i.log.gz') }

info myAppender: 'grails.app' }

DBAppender

This example configures a database appender. It uses a DriverManagerConnectionSource since it's from the plugin's unit tests, but using a DataSource or JNDI is supported and preferred:

import ch.qos.logback.classic.db.DBAppender
import ch.qos.logback.core.db.DriverManagerConnectionSource

logback = { appenders {

def connectionSource = dslInit(new DriverManagerConnectionSource( url: "$url", user: "$user", password: "$password", driverClass: "$driver"))

appender new DBAppender(name: 'db', connectionSource: connectionSource) }

info db: 'grails.app' }

You must create the database tables yourself. There are three tables, and the Logback distribution ships with sample DDL for several popular databases.

Note that this example uses the dslInit method; this is described below.

SMTPAppender

This example configures an email appender:

import ch.qos.logback.classic.PatternLayout
import ch.qos.logback.classic.net.SMTPAppender

logback = { appenders {

def layout = dslInit(new PatternLayout(outputPatternAsHeader: false, pattern: '%-4relative %-5level %class - %msg%n')) def smtp = new SMTPAppender(name: 'smtp', from: '$from', smtpHost: '$host', smtpPort: $port, layout: layout) smtp.context = context // need this now for the parser that's used for the To address smtp.addTo '$to' appender smtp }

info smtp: 'grails.app' }

This example also uses dslInit but due to configuration timing issues, the appender's LoggingContext must be set as soon as it's instantiated. The context variable is in scope and is the LoggingContext instance to use.

See the configuration tests for more information and examples of programmatic configuration.

Configuration issues

As you've seen, you can create Appenders and other components programmatically, and you use a similar syntax as in the Log4j DSL (i.e. call the appender method with your Appender as its argument). But the configuration process has changed in Logback, and all components must have a LoggingContext set, and usually must have their start() method called (analagous to the activateOptions() method in Log4j). This is done for you when you use the DSL to create an Appender or Encoder, but if you create your own you need an additional step. If you call the dslInit method, it will set the LoggingContext and call start() for you (and do other configuration steps that may be needed in the future). It returns the object that is passed to it to keep the DSL simple.