We highly recommend using Logback as an SLF4J binding (logging implementation).

From the Logback documentation

Logback is intended as a successor to the popular Log4J project, picking up where Log4J leaves off.

Logback’s architecture is sufficiently generic so as to apply under different circumstances. At present time, logback is divided into three modules, logback-core, logback-classic and logback-access.

See Logback’s documentation on reasons to switch from Log4j.

If you choose to use Logback, just include a jar dependency on ch.qos.logback:logback-classic.

E.g., with sbt:

"ch.qos.logback" % "logback-classic" % VERSION

Where, VERSION represents the version of Logback you want to use.

Similarly, with Maven:


This will provide the logback-classic SLF4J implementation. And when used in addition to the logging bridges provided transitively through the finatra/inject-slf4j module will configure your SLF4J logging implementation and correctly bridge all other legacy APIs.


To configure dynamic changing log levels with TwitterServer, be sure to also include a dependency on the TwitterServer Logback library.

With sbt:

"com.twitter" % "twitter-server-logback-classic" % VERSION

See the TwitterServer documentation for more information on configuration for dynamically changing log levels.

Logback Configuration

See the Logback documentation on configuration for detailed information on configuring Logback logging.


See the logback.xml configuration file in the http-server example project for example Logback configurations.

The example logback.xml configuration file makes use of Logback’s variable substitution


for configuring the <file/> output of the appenders. A variable’s value is specified at runtime as a Java system property, e.g.,


If a value is not provided the inlined default will be used, i.e., what is on the other side of the :-, e.g., access.log or service.log.

More information about Logback’s variable substitution may be found here.

Rerouting java.util.logging

Additional configuration is necessary to reroute the java.util.logging system. The reason is that the jul-to-slf4j bridge cannot replace classes in the java.util.logging package to do the redirection statically as it does for the other bridge implementations. Instead, it has to register a handler on the root logger and listen for logging statements like any other handler. It will then redirect those logging statements appropriately. This redirection is accomplished via SLF4J’s SLF4JBridgeHandler [documentation].

The util/util-slf4j-jul-bridge library provides a utility (and a mixin which applies the utility in the class constructor) which will attempt installation of the SLF4JBridgeHandler if it does not detect classes from slf4j-jdk14 on the classpath.

This utility is already mixed into c.t.server.TwitterServer and Finatra’s c.t.inject.app.App and thus JUL bridging to the SLF4J-API will be attempted automatically for extensions of those traits/classes.