## Chapter 5: Layouts

Authors: Ceki Gülcü, Sébastien Pennec

| Copyright © 2000-2006, QOS.ch This work is licensed under a Creative Commons Attribution-Noncommercial-No Derivative Works 2.5 License .

## What is a layout

While appenders are responsible for writing logging output to an appender dependent device, layouts are responsible for the format of the output. In case you were wondering, layouts have nothing to do with large estates in Florida. The `format()` method in the Layout class takes a object that represents the logging event and returns a String. A synopsis of the Layout interface is shown below.

public interface Layout extends ContextAware, LifeCycle {

String doLayout(Object event);

String getHeader();

String getFooter();

String getContentType();

This interface is really simple and yet is sufficent for many formatting needs.

## Logback classic

As we've seen, a Layout implementation takes as a parameter an object that represents a logging event. The typing of the parameter to `Object` is because logging events may have different ways of being designed. In logback classic, a logging event is represented by the `ch.qos.logback.classic.LoggingEvent` class. Therefore, all layouts in logback classic implement a sub-interface of `Layout` named `ClassicLayout` .

Here is what a `ClassicLayout` looks like:

public interface ClassicLayout extends Layout {

String doLayout(LoggingEvent event);

}

### PatternLayout

Logback ships with a flexible layout called `PatternLayout` . As all classic layouts, `PatternLayout` takes a logging event and returns a String. However, the returned String can be modified at will by tweaking its conversion pattern.

The conversion pattern of `PatternLayout` is closely related to the conversion pattern of the `printf()` function in the C programming language. A conversion pattern is composed of literal text and format control expressions called conversion specifiers. You are free to insert any literal text within the conversion pattern. Each conversion specifier starts with a percent sign (%) and is followed by optional format modifiers and a conversion character. The conversion character controls the type of data to use, e.g. logger name, level, date, thread name. The format modifiers control such things as field width, padding, and left or right justification. The following is a simple example.

Example 5.1: Sample usage of a PatternLayout (examples/chapter5/PatternSample.java) public class PatternSample { static public void main(String[] args) throws Exception { Logger rootLogger = (Logger) LoggerFactory.getLogger("root"); PatternLayout layout = new PatternLayout(); layout.setPattern("%-5level [%thread]: %message%n"); layout.start(); ConsoleAppender appender = new ConsoleAppender(); appender.setContext(rootLogger.getLoggerContext()); appender.setLayout(layout); appender.start(); rootLogger.addAppender(appender); rootLogger.debug("Message 1"); rootLogger.warn("Message 2"); } }

The conversion pattern is set to be "%-5level [%thread]: %message%n". Running PatternSample will yield the following output on the console.

DEBUG [main]: Message 1 WARN [main]: Message 2

Note that in the conversion pattern "%-5level [%thread]: %message%n" there is no explicit separator between literal text and conversion specifiers. When parsing a conversion pattern, `PatternLayout` is capable of differentiating between literal text (space characters, the brackets, colon character) and conversion specifiers. In the example above, the conversion specifier %-5level means the level of the logging event should be left justified to a width of five characters. Format specifiers will be explained in a short moment.

The recognized conversion characters and words are

Conversion Character or Word | Effect
--- | ---

c / l / lo / logger

Used to output the logger of the logging event. The logger conversion specifier can be optionally followed by precision specifier , that is a decimal constant in brackets.

If a precision specifier is given, then only the corresponding number of right most components of the logger name will be printed. By default the logger name is printed in full.

For example, for the category name "a.b.c" the pattern %logger{2} will output "b.c". See more examples of name abbreviations further down this document.

C / class

Used to output the fully qualified class name of the caller issuing the logging request. This conversion specifier can be optionally followed by precision specifier , that is a decimal constant in brackets.

If a precision specifier is given, then only the corresponding number of right most components of the class name will be printed. By default the class name is output in fully qualified form.

For example, for the class name "ch.logback.xyz.SomeClass", the pattern %class{1} will output "SomeClass". See more examples of name abbreviations further down this document.

WARNING Generating the caller class information is slow. Thus, it's use should be avoided unless execution speed is not an issue.

d / date | Used to output the date of the logging event. The date conversion specifier may be followed by a set of braces containing a date and time pattern strings {@link java.text.SimpleDateFormat}, ABSOLUTE , DATE or ISO8601 . For example, %d{HH:mm:ss,SSS} , %d{dd MMM yyyy ;HH:mm:ss,SSS} or %d{DATE} . If no date format specifier is given then ISO8601 format is assumed.
F / file | Used to output the file name where the logging request was issued. WARNING Generating caller file information is extremely slow. Its use should be avoided unless execution speed is not an issue.

caller

Used to output location information of the caller which generated the logging event.

The location information depends on the JVM implementation but usually consists of the fully qualified name of the calling method followed by the caller's source the file name and line number between parentheses.

The location information can be very useful. However, it's generation is extremely slow. It's use should be avoided unless execution speed is not an issue.

A precision specifier can be appended to the caller conversion specifier to configure the depth of the information to be displayed.

L / line | Used to output the line number from where the logging request was issued. WARNING Generating caller location information is extremely slow. It's use should be avoided unless execution speed is not an issue.
m / msg / message | Used to output the application supplied message associated with the logging event.
M / method | Used to output the method name where the logging request was issued. WARNING Generating caller location information is extremely slow. It's use should be avoided unless execution speed is not an issue.
n | Outputs the platform dependent line separator character or characters. This conversion character offers practically the same performance as using non-portable line separator strings such as "\n", or "\r\n". Thus, it is the preferred way of specifying a line separator.
p / le / level | Used to output the level of the logging event.
r / relative | Used to output the number of milliseconds elapsed since the start of the application until the creation of the logging event.
t / thread | Used to output the name of the thread that generated the logging event.

X / mdc

Used to output the MDC (mapped diagnostic context) associated with the thread that generated the logging event.

The X conversion character can be followed by the key for the map placed between braces, as in %X{clientNumber} where `clientNumber` is the key. The value in the MDC corresponding to the key will be output.

If no additional sub-option is specified, then the entire contents of the MDC key value pair set is output using a format key1=val1, key2=val2

See MDC class for more details.

throwable | Used to output the Throwable trace that has been bound to the LoggingEvent, by default this will output the full trace as one would normally find by a call to Throwable.printStackTrace(). The throwable conversion word can be followed by an option in the form %throwable{short} which will only output the first line of the ThrowableInformation.
% | The sequence %% outputs a single percent sign.

By default the relevant information is output as is. However, with the aid of format modifiers it is possible to change the minimum field width, the maximum field width and justification.

The optional format modifier is placed between the percent sign and the conversion character or word.

The first optional format modifier is the left justification flag which is just the minus (-) character. Then comes the optional minimum field width modifier. This is a decimal constant that represents the minimum number of characters to output. If the data item requires fewer characters, it is padded on either the left or the right until the minimum width is reached. The default is to pad on the left (right justify) but you can specify right padding with the left justification flag. The padding character is space. If the data item is larger than the minimum field width, the field is expanded to accommodate the data. The value is never truncated.

This behavior can be changed using the maximum field width modifier which is designated by a period followed by a decimal constant. If the data item is longer than the maximum field, then the extra characters are removed from the beginning of the data item and not from the end. For example, it the maximum field width is eight and the data item is ten characters long, then the first two characters of the data item are dropped. This behavior deviates from the printf function in C where truncation is done from the end.

Below are various format modifier examples for the logger conversion specifier.

Format modifier | Left justify | Minimum width | Maximum width | Comment
--- | --- | --- | --- | ---
%20c | false | 20 | none | Left pad with spaces if the category name is less than 20 characters long.
%-20c | true | 20 | none | Right pad with spaces if the logger name is less than 20 characters long.
%.30c | NA | none | 30 | Truncate from the beginning if the logger name is longer than 30 characters.
%20.30c | false | 20 | 30 | Left pad with spaces if the logger name is shorter than 20 characters. However, if logger name is longer than 30 characters, then truncate from the beginning.
%-20.30c | true | 20 | 30 | Right pad with spaces if the logger name is shorter than 20 characters. However, if logger name is longer than 30 characters, then truncate from the beginning.

### Option handling

A conversion specifier can be followed by options between curled brackets. We have already seen some of the possibilities offered by logback's option handling with, for example, the MDC conversion specifier: %mdc{someKey} .

However, there is much more to it than that.

The logger name conversion specifier can take an integer as a first option. This will use logback's abbreviation mechanism to display a shorter logger name, without loosing it's meaning.

The next table should clear things up.

Conversion Pattern | Logger name | Result
--- | --- | ---
%logger{10} | mainPackage.sub.sample.Bar | m.s.s.Bar
%logger{15} | mainPackage.sub.sample.Bar | m.s.sample.Bar
%logger{16} | mainPackage.sub.sample.Bar | m.sub.sample.Bar
%logger{26} | mainPackage.sub.sample.Bar | mainPackage.sub.sample.Bar

#### Evaluators

Another very useful way of adding options to a conversion specifier is when `PatternLayout` is used with `EventEvaluators` .

`EventEvaluators` have the responsability to check wether a given event matches a given criteria.

Let's look at an example using `EventEvaluators` . The following configuration file outputs the logging events to the console, displaying date, thread, level, message and caller data.

Since displaying the caller data of a logging event is very expensive, this information will be displayed only when the logging request comes from a specific logger, and whose message contains a certain string. By doing that, we make sure that only the most important logging requests will have their caller information generated and displayed, without penalizing application performance.

Here is how to configure logback to behave like we described:

Example 5.2: Sample usage of EventEvaluators (examples/chapter5/callerEvaluatorConfig.xml) <configuration> <evaluator name="DISP_CALLER_EVAL"> <Expression>logger.getName().contains("chapter5") && \ message.contains("stacktrace")</Expression> </evaluator> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <layout class="ch.qos.logback.classic.PatternLayout"> <param name="Pattern" value="%-4relative [%thread] %-5level - %msg \ %caller{2, DISP_CALLER_EVAL}%n" /> </layout> </appender> <root> <level value="debug" /> <appender-ref ref="STDOUT" /> </root> </configuration>

Let's test this configuration with the following code.

Example 5.2: Sample usage of EventEvaluators (examples/chapter5/EventEvaluatorExample.java) public class CallerEvaluatorExample { public static void main(String[] args) throws InterruptedException { Logger logger = (Logger) LoggerFactory.getLogger(CallerEvaluatorExample.class); LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); JoranConfigurator configurator = new JoranConfigurator(); configurator.setContext(lc); configurator.doConfigure(args[0]); for (int i = 0; i < 5; i++) { if (i == 3) { logger.debug("stacktrace logging statement" + i); } else { logger.debug("logging statement" + i); } } }

This excerpt does nothing very fancy. Five logging requests are issued, the third one being different from the others.

When a logging request is sent, the corresponding logging event will pass through the evaluation process. Here, obviously, the third request will match the evaluation, causing its caller data to be displayed.

Here is the output of the `EventEvaluatorExample` class.

0 [main] DEBUG - logging statement0 0 [main] DEBUG - logging statement1 0 [main] DEBUG - logging statement2 0 [main] DEBUG - logging statement3 Caller+0 at chapter5.CallerEvaluatorExample.main \ (CallerEvaluatorExample.java:25)

16 [main] DEBUG - logging statement4

Of course, one can change the expression to match one's specific situation. An expression testing logger name and request level could also be meaningful.

Let's look at a different situation. When exceptions are added to a logging request, they are usually displayed. But one can easily imagine that, for the sake of readability of a log file, one would want only a certain type of exceptions to be displayed.

The following configuration will allow that.

Example 5.3: Sample usage of EventEvaluators (examples/chapter5/exceptionEvaluatorConfig.xml) <configuration> <evaluator name="DISPLAY_EX_EVAL"> <Expression>marker.contains("IGNORE")</Expression> </evaluator> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <layout class="ch.qos.logback.classic.PatternLayout"> <param name="Pattern" value="%-4relative [%thread] %-5level - %msg%n \ %ex{full, DISPLAY_EX_EVAL}%n" /> </layout> </appender> <root> <level value="debug" /> <appender-ref ref="STDOUT" /> </root> </configuration>

With this configuration, each time a marker named IGNORE will be associated with a logging request containing an exception, no information will be displayed about the exception.

### HTMLLayout

HTMLLayout outputs events in an HTML table. Each row of the table corresponds to an event.

The content of the table columns are specified using a conversion pattern. See `PatternLayout` for documentation on the available patterns.

Note that the pattern %ex used to display an Exception is not the only way to display an Exception with this layout. If you use this pattern, a table column will be created to display the potential Exception's stacktrace.

However, a better solution is available in the form of implementations of the `IThrowableRenderer` interface. These implementations can be called and assigned to HTMLLayout to manage the display of anything related to Exceptions.

By default, a `DefaultThrowableRenderer` is assigned to the HTMLLayout. It writes the Exception on a new table row, along with its stacktrace, in a easily readable manner.

If one wants to use the &ex pattern anyway, then a `NOPThrowableRenderer` can be specified in the configuration file.

A user-specified external CSS file can be linked to the html page. In case one does not want to customize the html output, an internal CSS style is used.

The HTMLLayout is often used in conjunction with SMTPAppender, to send a nicely formatted html email. Of course, it can be used with any other Appender.

In case on wants to use the HTMLLayout with a SMTPAppender, here is a sample configuration file that can be used.

<configuration> <appender name="SMTP" class="ch.qos.logback.classic.net.SMTPAppender"> <layout class="ch.qos.logback.classic.html.HTMLLayout"> <param name="pattern" value="%relative%thread%mdc%level%class%msg" /> </layout> <throwableRenderer class="ch.qos.logback.classic.html.DefaultThrowableRenderer" /> <param name="From" value="sender.email@domain.net" /> <param name="SMTPHost" value="mail.domain.net" /> <param name="Subject" value="LastEvent: %class - %msg" /> <param name="To" value="destination.email@domain.net" /> </appender>

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

In this configuration file, the throwableRenderer element specifies the default implementation of IThrowableRenderer. It could be omitted, but is showed for educationnal purposes.

## Logback access

### PatternLayout

### HTMLLayout