There is so much to tell about the Western country in that day that it is hard to know where to start. One thing sets off a hundred others. The problem is to decide which one to tell first.

—JOHN STEINBECK, East of Eden

Manual · Appenders · Appenders: Console and File

Appenders: Console and File

This page continues the Appenders chapter. The overview introduces the Appender interface, AppenderBase, and OutputStreamAppender (including its encoder and immediateFlush properties and the class diagram of its subclasses).

Here we turn to the concrete stream-oriented appenders that most applications configure first: ConsoleAppender, JansiConsoleAppender, and FileAppender. All three build on OutputStreamAppender. Rolling files are covered separately under Rolling file.

ConsoleAppender

The ConsoleAppender, as the name indicates, appends on the console, or more precisely on System.out or System.err, the former being the default target. ConsoleAppender formats events with the help of an encoder specified by the user. Encoders will be discussed in a subsequent chapter. Both System.out and System.err are of type java.io.PrintStream. Consequently, they are wrapped inside an OutputStreamWriter which buffers I/O operations.

WARNING Please note the console is comparatively slow, even very slow. You should avoid logging to the console in production, especially in high volume systems.

Property Name Type Description
encoder Encoder See OutputStreamAppender properties.
target String One of the String values System.out or System.err. The default target is System.out.
withJansi boolean

since 1.6.3 Deprecated. Prefer JansiConsoleAppender instead of setting withJansi on a plain ConsoleAppender. When set to true, logback emits a deprecation warning and this option will be removed in a future release.

By default withJansi is false. Setting it to true still activates Jansi via reflection so that ANSI color codes work on platforms that need it (notably Windows). The implementation probes JLine's org.jline.jansi.AnsiConsole first and falls back to the legacy FuseSource org.fusesource.jansi.AnsiConsole. Put the matching artifact on the class path (org.jline:jansi-core or org.fusesource.jansi:jansi). Unix-based systems such as Linux and macOS already support ANSI color codes by default.

Here is a sample configuration that uses ConsoleAppender.

Example: ConsoleAppender configuration (logback-examples/​src/main/resources/​chapters/appenders/​conf/logback-Console.​xml)

<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>%-4relative [%thread] %-5level %logger{35} -%kvp- %msg %n</pattern>
    </encoder>
  </appender>

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

Requires a server call.

Requires a server call.

After you have set your current path to the logback-examples directory and set up your class path, you can give the above configuration file a whirl by issuing the following command:

java chapters.appenders.​ConfigurationTester src/main/java/chapters/​appenders/conf/​logback-Console.xml

JansiConsoleAppender

since 1.6.3 The JansiConsoleAppender is a ConsoleAppender that always writes through JLine's org.jline.jansi.AnsiConsole. It is the recommended way to enable ANSI sequences on platforms that need Jansi (notably Windows). Unlike the deprecated withJansi path on ConsoleAppender, this class talks to AnsiConsole directly and does not use reflection.

You must place org.jline:jansi-core on the class path. On start, the appender calls AnsiConsole.systemInstall() and routes output to AnsiConsole.out() or AnsiConsole.err() according to the target property. On stop, if this appender performed the install, it pairs that call with AnsiConsole.systemUninstall(). As with ConsoleAppender, stop flushes the console stream but does not close process-wide stdout or stderr.

JansiConsoleAppender admits the same encoder and target properties as ConsoleAppender. You do not set withJansi; Jansi wrapping is always applied.

Here is a sample configuration that uses JansiConsoleAppender instead of a plain ConsoleAppender with <withJansi>true</withJansi>:

DEPRECATED

<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
  <withJansi>true</withJansi>
  <encoder>
    <pattern>%highlight(%-5level) %logger{35} - %msg%n</pattern>
  </encoder>
</appender>

RECOMMENDED

<appender name="STDOUT" class="ch.qos.logback.core.JansiConsoleAppender">
  <encoder>
    <pattern>%highlight(%-5level) %logger{35} - %msg%n</pattern>
  </encoder>
</appender>

FileAppender

The FileAppender, a subclass of OutputStreamAppender, appends log events into a file. The target file is specified by the File option. If the file already exists, it is either appended to, or truncated depending on the value of the append property.

Property Name Type Description
append boolean If true, events are appended at the end of an existing file. Otherwise, if append is false, any existing file is truncated. The append option is set to true by default.
encoder Encoder See OutputStreamAppender properties.
file String The name of the file to write to. If the file does not exist, it is created. On the MS Windows platform users frequently forget to escape backslashes. For example, the value c:\temp\test.log is not likely to be interpreted properly as '\t' is an escape sequence interpreted as a single tab character (\u0009). Correct values can be specified as c:/temp/test.log or alternatively as c:\\temp\\test.log. The File option has no default value.

If the parent directory of the file does not exist, FileAppender will automatically create it, including any necessary but nonexistent parent directories.

bufferSize FileSize

The bufferSize option set the size of the output buffer in case immediateFlush option is set to false. Default value for bufferSize is 8192. The value 256 KB seems to sufficient even in cases of very heavy and persistent loads.

Options in defined in units of "FileSize" can be specified in bytes, kilobytes, megabytes or gigabytes by suffixing a numeric value with KB, MB and respectively GB. For example, 5242880, 5120KB, 5120 KB, 5MB, 5 MB, 2 GB and 2GB are all valid values, with the first five being equivalent. A numerical value with no suffix is taken to be in units of bytes.

prudent boolean In prudent mode, FileAppender will safely write to the specified file, even in the presence of other FileAppender instances running in different JVMs, potentially running on different hosts. The default value for prudent mode is false.

Prudent mode can be used in conjunction with RollingFileAppender although some restrictions apply.

Prudent mode implies that append property is automatically set to true.

Prudent more relies on exclusive file locks. Experiments show that file locks approximately triple (x3) the cost of writing a logging event. On an "average" PC writing to a file located on a local hard disk, when prudent mode is off, it takes about 10 microseconds to write a single logging event. When prudent mode is on, it takes approximately 30 microseconds to output a single logging event. This translates to logging throughput of 100'000 events per second when prudent mode is off and approximately 33'000 events per second in prudent mode.

Prudent mode effectively serializes I/O operations between all JVMs writing to the same file. Thus, as the number of JVMs competing to access a file increases so will the delay incurred by each I/O operation. As long as the total number of I/O operations is in the order of 20 log requests per second, the impact on performance should be negligible. Applications generating 100 or more I/O operations per second can see an impact on performance and should avoid using prudent mode.

Networked file locks When the log file is located on a networked file system, the cost of prudent mode is even greater. Just as importantly, file locks over a networked file system can be sometimes strongly biased such that the process currently owning the lock immediately re-obtains the lock upon its release. Thus, while one process hogs the lock for the log file, other processes starve waiting for the lock to the point of appearing deadlocked.

The impact of prudent mode is highly dependent on network speed as well as the OS implementation details. We provide a very small application called FileLockSimulator which can help you simulate the behavior of prudent mode in your environment.

Immediate Flush By default, each log event is immediately flushed to the underlying output stream. This default approach is safer in the sense that logging events are not lost in case your application exits without properly closing appenders. However, for significantly increased logging throughput, you may want to set the immediateFlush property to false.

Below is an example of a configuration file for FileAppender:

Example: FileAppender configuration (logback-examples/​src/main/resources/​chapters/appenders/​conf/logback-fileAppender.​xml)

<configuration>

  <appender name="FILE" class="ch.qos.logback.core.FileAppender">
    <file>testFile.log</file>
    <append>true</append>
    <!-- set immediateFlush to false for much higher logging throughput -->
    <immediateFlush>true</immediateFlush>
    <!-- encoders are assigned the type
         ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
    <encoder>
      <pattern>%-4relative [%thread] %-5level %logger{35} -%kvp- %msg%n</pattern>
    </encoder>
  </appender>

  <root level="DEBUG">
    <appender-ref ref="FILE" />
  </root>
</configuration>

Requires a server call.

Requires a server call.

After changing the current directory to logback-examples, run this example by launching the following command:

java chapters.appenders.​ConfigurationTester src/main/java/chapters/​appenders/conf/​logback-fileAppender.​xml

Uniquely named files (by timestamp)

During the application development phase or in the case of short-lived applications, e.g. batch applications, it is desirable to create a new log file at each new application launch. This is fairly easy to do with the help of the <timestamp> element. Here's an example.

Example: Uniquely named FileAppender configuration by timestamp (logback-examples/​src/main/resources/​chapters/appenders/​conf/logback-timestamp.​xml)

<configuration>

  <!-- Insert the current time formatted as "yyyyMMdd'T'HHmmss" under
       the key "bySecond" into the logger context. This value will be
       available to all subsequent configuration elements. -->
  <timestamp key="bySecond" datePattern="yyyyMMdd'T'HHmmss"/>

  <appender name="FILE" class="ch.qos.logback.core.FileAppender">
    <!-- use the previously created timestamp to create a uniquely
         named log file -->
    <file>log-${bySecond}.txt</file>
    <encoder>
      <pattern>%logger{35} -%kvp- %msg%n</pattern>
    </encoder>
  </appender>

  <root level="DEBUG">
    <appender-ref ref="FILE" />
  </root>
     </configuration>

Requires a server call.

Requires a server call.

The timestamp element takes two mandatory attributes key and datePattern and an optional timeReference attribute. The key attribute is the name of the key under which the timestamp will be available to subsequent configuration elements as a variable. The datePattern attribute denotes the date pattern used to convert the current time (at which the configuration file is parsed) into a string. The date pattern should follow the conventions defined in SimpleDateFormat. The timeReference attribute denotes the time reference for the time stamp. The default is the interpretation/parsing time of the configuration file, i.e. the current time. However, under certain circumstances it might be useful to use the context birth time as time reference. This can be accomplished by setting the timeReference attribute to "contextBirth".

Experiment with the <timestamp> element by running the command:

java chapters.appenders.​ConfigurationTester src/main/resources/​chapters/appenders/​conf/logback-timestamp.​xml

To use the logger context birthdate as time reference, you would set the timeReference attribute to "contextBirth" as shown below.

Example: Timestamp using context birthdate as time reference (logback-examples/​src/main/resources/​chapters/appenders/​conf/logback-timestamp-contextBirth.​xml)

<configuration>
  <timestamp key="bySecond" datePattern="yyyyMMdd'T'HHmmss" 
             timeReference="contextBirth"/>
  ...
</configuration>