A logging framework is superior to just using println because it can support

  • Log rotation (for daemons)
  • Configurable log format
  • Configurable log level

There are several libraries to use when it comes to logging in Java. For the practical programmer, the important things to note are

  • What to include in the dependency resolution tool. e.g. sbt, pom, gradle.
  • How to configure the logger. By default the configuration is usually found in the resources directory. e.g. src/main/resources.

Java

Java util logging

This is included in the JRE. Configuration is done by setting the system property java.util.logging.config.file=logging.properties. Docs

import java.util.logging.Logger;
public class App {
    private static Logger logger = Logger.getLogger("Test");
    public static void main(String[] args) {
        logger.info("Test");
    }
}

Note that one can write a custom LogManager class to do all the

Simple Logging Facade for Java (SLF4J)

J.U.L is a logging engine and slf4j is a logging facade, an abstraction on top of the logging engine.

The idea here is that libraries author can call methods on this abstraction and applications can choose what logging implementation to use.

The configuration for this depends on the underlying implementation.

The manual is actually quite succinct and has all the information to get started. However for an even more terse set of instructions:

First include the slf4j-api.jar in the class path, and then have the following in code. Note that this is quite similar to j.u.l code above.

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class HelloWorld {
  public static void main(String[] args) {
    Logger logger = LoggerFactory.getLogger(HelloWorld.class);
    logger.info("Hello World");
  }
}

Then include one of the implementations. This diagram provides a visual guide on the different choices.

As of this writing, I always simply include slf4j-simple.jar using the default configuration.

Logback is another popular one, which is used by play framework. The configuration is done

One gotcha with SLF4J is that if no implementation/binding is found, then the default is a NOP logger.

Log4j 2

Its website states that it’s an upgrade of log4j that is more performant than logback. It also claims that it is compliant with SLF4J libraries. Personally I haven’t had the chance to use this so I can’t comment on it as of now.

Scala

The Java logging framework in the previous section applies here too. However, there is a convenient wrapper scala-logging which makes logging slightly easier to use.

To me the greatest win from using this is one can just mixin the logger set up producing succinct code.

Another benefit, which admittedly I haven’t personally used, is lazily compute expensive messages. Suppose you set the logging level to be info, and you have a logger.debug(...) line that does a lot of work to compute the message, the library’s macro prevents that line from being called by adding a guard during the compilation step. The following code snippet would illustrate the point.


package slog

import com.typesafe.scalalogging.StrictLogging
import org.slf4j.LoggerFactory

// Uses slf logger directly
object slf {
  def main(args: Array[String]): Unit = {
    val logger = LoggerFactory.getLogger("main")
    val start = System.currentTimeMillis()
    logger.info("normal message")
    logger.debug(exp.expensive())
    val end = System.currentTimeMillis()
    println(end - start) // Prints 1015
  }
}

// Uses scala logging wrapper
object slf2 extends StrictLogging {
  def main(args: Array[String]): Unit = {
    val start = System.currentTimeMillis()
    logger.info("normal message")
    logger.debug(exp.expensive())
    val end = System.currentTimeMillis()
    println(end - start) // Prints 13
  }
}

object exp {
  def expensive()  : String = {
    Thread.sleep(1000)
    "should show in debug"
  }
}

Glossary

  • log4j : An old logging framework. End of life in 2015.
  • logback : A successor to log4j written by the same developer, and supports SLF4J natively.
  • log4j2 : Another successor to log4j that supports slf4j. A newer logging framework compared to logback.
  • slf4j : A logging facade to abstract away the logging framework implementation.
  • j.u.l : The logging framework bundled in the JRE.

Also see wikipedia