Introduction to Logging With Finatra

Finatra uses the SLF4J API for framework logging. By coupling the framework to only the SLF4J API, application developers are free to choose their logging implementation.

From the SLF4J documentation

“The Simple Logging Facade for Java serves as a simple facade or abstraction for various logging frameworks, such as java.util.logging, Logback and log4j. SLF4J allows the end-user to plug in the desired logging framework at deployment time.”

finatra/inject/inject-slf4j provides transitively SLF4J bridges for the following logging providers:

  • Log4j
  • commons-logging
  • java.util.logging: there is a performance penalty for intercepting jul log messages, so c.t.inject.server.TwitterServer will install the SLF4JBridgeHandler which mitigates most of the performance penalty. Note, if you are not using the c.t.inject.server.TwitterServer or a subclass, e.g., you are building a command line application directly with c.t.inject.app.App, make sure the framework includes the LoggingModule as a framework module.

Since SLF4J is an interface, it requires an actual logging implementation. However, you should ensure that you do not end-up with multiple logging implementations on your classpath, e.g., you should not have multiple SLF4J bindings (slf4j-nop, slf4j-log4j12, slf4j-jdk14, etc.) nor a java.util.logging implementation, etc. on your classpath as these are all competing implementations and since classpath order is non-deterministic this will lead to unexpected logging behavior.

While there are several scala-wrappers for SLF4J, Finatra uses and exposes some additional features on top of the TwitterUtil util-slf4j-api project.

The main logging utility is the c.t.inject.Logging trait which can be mixed into any object or class:

import com.twitter.inject.Logging

class MyClass extends Logging {
  def foo() = {
    info("Calculating...")
    "bar"
  }
}

This trait is a wrapper with some added utility over the c.t.util.logging.Logging.

Scala users should prefer using the logging methods of the c.t.inject.Logging trait (as opposed to directly accessing the Logger instance) as these methods use “call-by-name” parameters.

For more information see the scaladocs for c.t.inject.Logging or the util-slf4j-api README.