The Logback Project has three modules: logback-core, logback-classic and logback-access. The logback-core has the core functions for other two modules. The logback-classic implements the SLF4J API. The logback-access integrates with the Servlet containers to provide HTTP-access log functionality. Logback is fast, native SLF4J, well-documented and dynamic configurable.

1 Introduction

Logback-classic moedule require three files: slf4j-api.jar, logback-core.jar, and logback-classic.jar. To use it, use factory to create a logger and then call its logging methods. For example:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
package chapters.introduction;

import org.slf4j.Logger
import org.slf4j.LoggerFactory
import ch.qos.logback.classic.LoggerContext
import ch.qos.logback.core.util.StatusPrinter

object hi {

  def main(args: Array[String]) = {
    val logger = LoggerFactory.getLogger("chapters.introduction.HelloWorld2")
    logger.debug("Hello world.")

    // print internal state
    val lc = LoggerFactory.getILoggerFactory().asInstanceOf[LoggerContext]
    StatusPrinter.print(lc)
  }
}

The default is to use a ConsoelAppender to the root logger. the last two statements print the internal states. An appender is a class that works as an output destination. Common appenders include console, file, syslog, TCP socket, Postgresql, MySQL, and JMS.

Enable logging in an application has three steps: configure, create a logger and call printing methods.

2 Architecture

Logback is build upon three main classes Logger, Appender, and Layout to log messages according to message type and level and to control message format.

A LoggerContext is responsible for creating loggers and arranging them in a tree hierarchy based on their name. There is a root logger that is the top ancestor of every logger. It can be retrieved by LoggerFactory.getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME).

There are five printing methods: trace, debug, info, warn and error.

Loggers may be assigned one of five possible levels defined in ch.qos.logback.classic.Level class. It defines six levels: OFF, TRACE, DEBUG, INFO, WARN, and ERROR. If a logger is not assigned a level, then it inhereits from its closes ancestor that has an assigned level. By default, the root logger has a default leval of DEBUG.

A logging request is enabled if its level is higher than or equal to the effective level of its logger. Otherwise, it is disabled.

To set a log level at runtime, create a logback logger of type ch.qos.logback.classic.Logger and call its setLevel method.

Calling LoggerFactory.getLogger with the same name always returns a reference to the same logger object.

The addAppender method adds an appender to a given logger. Each enabled logging request will be forwarded to all the appenders in that logger and appenders higher in the hierarchy. This additivity flag can be set to false to disable this feature.

A layout formats the logging request. A common layout is PatternLayout.

The logging method may take multiple paramters and this feature can be used to avoid unnecessary arguments evaluation.

A logging method involves the following steps:

  • Get the filter chain decision: the optional TurboFilter chain set a context-wide filter based on Marker, Level, Logger, message, or the Throwable that are assoicated with each logging request. If the result is FilterReply.DENY, the logging request is dropped. If it is FilterReply.NEUTRAL, go to the next step. If it is FilterReply.ACCEPT, skip the next step.
  • Apply the basic selection rule: check the effect level of logger.
  • Create a LoggingEvent object with all relevant data, some might be initialized lazily.
  • Invoke appenders: call the doAppend() method of all applicable appenders that might have custom filters attached.
  • Format the output: appenders may format or delegate the formatting.
  • Send out the LoggingEvent.

3 Configuration

Logback can be configured either programmatically or with a configuration script in XML or Groovy format.

3.1 Loading Configuration

The search order for configuration files are as the following:

  • logback-test.xml in classpath
  • logback.groovy in classpath
  • logback.xml in classpath
  • Service provider loading for com.qos.logback.classic.spi.Configurator
  • The default BasicConfigurator that log to console at debug level

The default configure in xml format:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
<configuration>
  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <!-- encoders are assigned the type
         ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
    <encoder>
      <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
    </encoder>
  </appender>

  <root level="debug">
    <appender-ref ref="STDOUT" />
  </root>
</configuration>

To configure individual logger, use the following syntax:

1
<logger name="chapters.configuration" level="INFO"/>

If warnings or errors occur during the parsing of the configuration file, logback will automatically print its internal status data. To ask logback report status for all, use <configuration debug="true"> to let it print status message in certain situations. The best is to use the code to print internal status.

You may specify the location of configuration file using command line option java -Dlogback.configurationFile=/path/to/config.xml MyApp.

Set <configuration scan="true" scanPeriod="30 seconds"> to enalbe auto scan of configuraiton file.

To log packaging data <configuration packagingData="true">.

Install a shutdown hook: <shutdownHook/>

3.2 Configuration Syntax

One <configuration> element, containing zero or more <appender> elements, followed by zero or more <logger> elements, followed by at most one <root> element. Tag names are case insensitive. camelCase naming is recommended.

A <logger> element takes exactly one mandatory name attribute, an optional level attribute, and an optional additivity attribute, admitting the values true or false. The special case-insensitive value INHERITED, or its synonym NULL, will force the level of the logger to be inherited from higher up in the hierarchy. The <logger> element may contain zero or more <appender-ref> elements; each appender thus referenced is added to the named logger.

The <root> element configures the root logger. It supports a single attribute, namely the level attribute.

The <appender> element takes two mandatory attributes: the name attribute specifies the name of the appender whereas the class attribute specifies the fully qualified name of the appender class to instantiate. The <appender> element may contain zero or one <layout> elements, zero or more <encoder> elements and zero or more <filter> elements.

The <layout> element takes a mandatory class attribute specifying the fully qualified name of the layout class to instantiate. <layout> may contain other elements corresponding to properties of the layout instance. PatternLayout is used if not <layout> element.

You can define scoped vairables useing the <property> element. It support conditional processing.

4 Appender

An appender implements the ch.qos.logback.core.Appender interface that defines the doAppend(event) method. For logback classic module, the event has a type of ILoggingEvent. An appender may delegate the actual formatting to a Layout or an Encoder object. Logback core module has pre-defined appenders such as OutputStreamAppender, ConsoleAppender, FileAppender, RollingFileAppender.

Logback classic module adds SocketAppender, SSLSocketAppender, SMTPAppender, DBAppender, SyslogAppender, SiftingAppender, and AsyncAppender.

AsyncAppender logs ILoggingEvents asynchronously. It acts solely as an event dispatcher and must therefore reference another appender in order to do anything useful.

5 Encoder and Layout

Encoders are responsible for transforming an event into a byte array and writing out the byte array into an OutputStream.

The PatternLayoutEncoder wraps PatternLayout. In order to facilitate parsing of log files, logback can insert the pattern used for the log output at the top of log files. This feature is disabled by default. It can be enabled by setting the outputPatternAsHeader property to true.

Layouts are logback components responsible for transforming an incoming event into a String. The format() method in the Layout interface takes an object that represents an event (of any type) and returns a String. Logback ships with an encoder named PatternLayoutEncoder, designed solely for the purpose of wrapping a PatternLayout instance so that it can be seen as encoder.

The conversion pattern of PatternLayout is closely related to the conversion pattern of the C’s printf() function. A conversion pattern is composed of literal text and format control expressions called conversion specifiers.

Each conversion specifier starts with a percent sign % and is followed by optional format modifiers, a conversion word and optional parameters between braces. The conversion word controls the data field to convert, e.g. logger name, level, date or thread name.

6 Mapped Diagnostic Context (MDC)

The MDC class lets the developer place information in a diagnostic context that can be subsequently retrieved by certain logback components. The MDC manages contextual information on a per thread basis. A child thread does not automatically inherit a copy of the mapped diagnostic context of its parent.

Normally, a put() operation should be balanced by the corresponding remove() operation. Supporting MDC in thread pool requires to save the MDC data at session start and remove at sesssion end. It is recommended that MDC.getCopyOfContextMap() is invoked on the original (master) thread before submitting a task to the executor. When the task runs, as its first action, it should invoke MDC.setContextMapValues() to associate the stored copy of the original MDC values with the new Executor managed thread.

Use the %X{key} specifier to generate output of MDC.