Scala-Style Logging with Grizzled-SLF4J

Problem: You want to add logging to an application in a more Scala-specific way than simply using SLF4J.

Solution

Grizzled-SLF4J is a thin wrapper around SLF4J that gives you logging in a more Scala-like way.

To get started with Grizzled-SLF4J, create a simple SBT project, then edit your build.sbt file so it has the dependencies you’ll need:

name := "Grizzled"

version := "1.0"

scalaVersion := "2.10.0"

libraryDependencies ++= Seq("org.slf4j" % "slf4j-api" % "1.7.5",
                            "org.slf4j" % "slf4j-simple" % "1.7.5",
                            "org.clapper" %% "grizzled-slf4j" % "1.0.1")

Then create a simple test class to use Grizzled-SLF4J. Put the following code in a file named Main.scala in the root directory of your SBT project:

import grizzled.slf4j.Logger

object Main extends App {

  // create a logger manually using one of these approaches
  //val logger = Logger("com.alvinalexander.test.Main")
  //val logger = Logger(classOf[Main])
  val logger = Logger[this.type]

  logger.info("Hello, world")

}

As you can see from that example, you can import the Grizzled-SLF4J Logger class, then manually create a Logger instance in several different ways in a class or object. Running this object with sbt run prints the following output to STDOUT:

[run-main] INFO Main$ - Hello, world

As a second approach, instead of manually creating a logger instance, you can mix in the Grizzled-SLF4J Logging trait, which creates the logger instance for you:

import grizzled.slf4j.Logging

object Main extends App with Logging {

  logger.info("Hello, world")

}

Running your object with this approach yields the same output as before:

[run-main] INFO Main$ - Hello, world

Discussion

Grizzled-SLF4J is a simple Scala wrapper around the well-known SLF4J library, has good documentation, and has recently been updated. Other libraries take a similar approach, but Grizzled-SLF4J currently has the best documentation and most recent updates.

A nice feature of Grizzled-SLF4J is that parameters to method calls like log.info and log.debug are call-by-name parameters. For instance, the Grizzled-SLF4J documentation shows that the debug method is defined like this:

@inline final def debug(message: => Any) =
    if (debugIsEnabled) log(message)

The documentation states:

“Thus, debug isn’t a method taking a string; instead, it’s a method taking a function that returns a string ... However, because message is a function that returns a string, it isn’t evaluated until it is called -- which is after the test that determines whether it should be logged.”

Because message is a call-by-name parameter, it isn’t evaluated until after the debugIsEnabled check, and if debugIsEnabled is false, it won’t be evaluated at all. This is another benefit of using Grizzled-SLF4J.

See Also