Typesafe's scala-logging and Logback

For my application, I want to introduce logging to an actual log file and not only to STDOUT. I now use Typesafe’s scala-logging and added Logback 1.4 as a dependency.

Currently I use it like this:

private val logger = com.typesafe.scalalogging.Logger(getClass)
logger.debug("Hello, logging!")

This writes the log message to STDOUT, but I want to use an actual log file. As far as I understand, this is done using Logback. Is Logback automatically used by Scala Logging if it is included as a dependency? Do I need to configure Scala Logging to use Logback?

Yes, you only need to add logback as one of your dependencies and then configure it using the logback.xml file; which is usually placed on the src/main/resources

If you wonder how logback is used under the hood is thanks to runtime reflection.

1 Like

Thank you, your answer already helps a lot!

If I understand you correctly that means that all config I want to do to format and logging target I do via the Logback config, right?

Yes, all scalaloggin will do in runtime is delegate the calls to logback thus all configuration should be done using logback.xml

1 Like

I set it up as described and it works if I run my application within IntelliJ but if I build it and run it externally I get the following logging output:

SLF4J: No SLF4J providers were found.

Do you have any idea what I did wrong?

How did you added the logback dependency? Share the relevant lines of your build.sbt file.
Also, where did you put the logback.xml file?
Also, how are you building and running it?

This is my build.sbt:

name := "App"

version := "0.2"

scalaVersion := "2.13.8"

mainClass in assembly := Some("com.example.app.Main")
assemblyJarName in assembly := "gcm.jar"
assemblyMergeStrategy in assembly := {
  case PathList("META-INF", xs@_*) => MergeStrategy.discard
  case PathList("reference.conf") => MergeStrategy.concat
  case x => MergeStrategy.first
}

libraryDependencies += "org.apache.commons" % "commons-lang3" % "3.12.0"
libraryDependencies += "commons-io" % "commons-io" % "2.11.0"
libraryDependencies += "com.typesafe" % "config" % "1.4.2"
libraryDependencies += "ch.qos.logback" % "logback-classic" % "1.4.0"
libraryDependencies += "com.typesafe.scala-logging" %% "scala-logging" % "3.9.5"

libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.12"

I am not totally sure but I can think of two things that may be the problem.

  1. case PathList("META-INF", xs@_*) => MergeStrategy.discard I think you are discarding more than necessary here and maybe in one of such files is the info required to load logback on runtime.
  2. IIUC the 1.4.0 version of logback is intended for Java 9+ and requires its module system, are you sure you are running on an appropriate runtime? Maybe try using one of the 1.2 or 1.3 versions.

To be honest: I am not entirely sure what all that does, that discarding and merging. I found this example that made my über-JAR work, and I did not change it since then. I know that’s not good practice, but it led to a quick win, and I should investigate what all that stuff does.

I use a Java 18 JRE.