scalaloggingslf4j

Scala logging line numbers don't match using slf4s/slf4j?


Does anyone know if there is a way to do logging that outputs real line numbers to the console? I'm trying to get into Scala here, but without being able to get basic stuff like this that I depend on, it's really hard to get much going.

I have set up SLF4J to wrap with slf4j - log4j - jcl-over-slf4j. The problem is I get line numbers that do not match at all. The are much higher line numbers than the Scala class even contains. Is this because the line numbers are actually Java-intermediate line numbers?

Is there any EASY way to get set up logging that meets these requirements?:

  1. interoperable, working with both Java & Scala
  2. as easy to change the logging level of individual packages as easily as Log4j
  3. provides ACCURATE line numbers.

Solution

  • I have found that logback (by Ceki Gülcü) works great and preserves line numbers too!
    (And it works as a replacement for log4j: Awesome!)

    import ch.qos.logback._
    import org.slf4j._
    
    object Main {
    
        def logger = LoggerFactory.getLogger("Main")
        var thingy = {
            x:Int =>
            logger.info("x=" + x)
            x + 1
        }
        def main(args: Array[String]) {
            logger.info("Hello.")
            logger.info("Hello again!")
    
            val myInts : List[Int] = List(-25,1,5,20)
    
            val myInts2 : List[Int] = myInts.filter { x:Int => x > 0 }
    
            logger.info("my ints2:" + myInts2)
    
            val myInts3 = myInts2.map(p =>  p * 2 )
            logger.info("my ints3:" + myInts3)
    
            logger.info(thingy(1) + "")
        }
    }
    

    For anyone struggling to get started with Scala, this is what I did to get the basic skeleton up:

    1) Download sbt-launcher.jar and put it someplace like /opt/
    I used "sbt-launch-0.7.5.RC0.jar"

    2) Create a bash script as a shortcut to the sbt launcher in nano /opt/bin/sbt:

    #!/bin/bash
    java -jar /opt/sbt-launch-0.7.5.RC0.jar "$@"
    

    (make it executable)

    $ sudo chmod ug+x ./sbt
    

    Make sure it's in your path too.

    3) Create and configure the sbt project:

    $ mkdir ./sc01
    $ cd ./sc01
    $ sbt
    $ mkdir ./project/build</pre>
    $ nano ./project/build/Project.scala</pre>
    

    put this in there:

    import sbt._
    
    class sc01(info: ProjectInfo) extends DefaultProject(info)
    {
        // dependencies
        val logback_core = "ch.qos.logback" % "logback-core" % "0.9.24" % "compile" //LGPL 2.1
        val logback_classic = "ch.qos.logback" % "logback-classic" % "0.9.24" % "compile" //LGPL 2.1
        val log4j_over_slf4j = "org.slf4j" % "log4j-over-slf4j" % "1.6.1"
    
    
       // if you are going to have any unmanaged (manually-added) jars
       //    def baseDirectories = "lib"
       //    def extraJars = descendents(baseDirectories, "*.jar")
       //    override def unmanagedClasspath = super.unmanagedClasspath +++ extraJars
    
        // tasks - easy to define
        lazy val hi = task { println("Hello World"); None }
    
        // classpath
        //override def mainScalaSourcePath = "src"
    
    }
    

    4) Paste the stuff from above into Main:

    $ nano ./src/main/scala/Main.scala
    

    5) I almost forgot! put this in /src/main/resources/logback.xml
    (it's required to get the line numbers)

    <configuration>
    
        <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
            <!-- encoders are assigned the type
         ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
            <encoder>
                <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} %line --- %msg%n</pattern>
            </encoder>
        </appender>
    
        <root level="debug">
            <appender-ref ref="STDOUT" />
        </root>
    </configuration>
    

    6) $ sbt

    Now you should be in the sbt console in your shell:

    > update
    > compile
    > run
    

    Hope this helps.