Saturday, November 23, 2013

Generic logback.xml

I've started using a generic logback.xml file for my projects which use logging:

<?xml version="1.0"?>
<configuration debug="${log.debug:=false}">
  <property resource="logback-style.properties"/>
  <appender name="console"
      class="ch.qos.logback.core.ConsoleAppender">
    <encoder
        class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
      <pattern>${${log.style:-standard}}</pattern>
    </encoder>
  </appender>
  <root level="${log.level:-warn}">
    <appender-ref ref="console"/>
  </root>
  <include resource="logback-included.xml" optional="true"/>
  <contextListener
      class="ch.qos.logback.classic.jul.LevelChangePropagator"/>
  <jmxConfigurator/>
</configuration>

Some explanation:

  • I make use of the substitution with default feature to make use of system properties:
    log.debug
    Setting this to "true" gets logback to log during configuration, default is "false"
    log.style
    See below
    log.level
    This adjusts the global log level, default is "warn" so only errors and warnings log
  • Reading variables from a property file as a resource lets me externalize them to the classpath, in particular, the log style (see the next item).
  • The name nesting for substitution feature is neat: it lets you use the value of a variable as the name of another variable. For log.style I read a log format string from a properties file, using another property for the key name.
  • File inclusion let me keep the boilerplate in this example, and the application-specific bits in a separate logback XML file.
  • Lastly I add a context listener to hook java.util.logging into logback and turn on JMX support. I do these last for some small performance gain.

Here is one example log-style.properties:

standard=%date{yyyy-MM-dd'T'HH:mm:ss.SSS'Z',UTC} %level [%thread] %logger - %message%n

Update:

A handy trick to automatically lower logging to "debug" when "logback.debug" is true, best placed near the top:

<if condition='property("logback.debug").equals("true")'>
    <then>
        <variable name="log.level" value="debug"/>
    </then>
</if>