Logging in Scala

前端 未结 14 2028
南旧
南旧 2020-12-07 06:51

What is a good way to do logging in a Scala application? Something that is consistent with the language philosophy, does not clutter the code, and is low-maintenance and uno

相关标签:
14条回答
  • 2020-12-07 07:35

    I pulled a bit of work form the Logging trait of scalax, and created a trait that also integrated a MessageFormat-based library.

    Then stuff kind of looks like this:

    class Foo extends Loggable {
        info( "Dude, I'm an {0} with {1,number,#}", "Log message", 1234 )
    }
    

    We like the approach so far.

    Implementation:

    trait Loggable {
    
        val logger:Logger = Logging.getLogger(this)
    
        def checkFormat(msg:String, refs:Seq[Any]):String =
            if (refs.size > 0) msgfmtSeq(msg, refs) else msg 
    
        def trace(msg:String, refs:Any*) = logger trace checkFormat(msg, refs)
    
        def trace(t:Throwable, msg:String, refs:Any*) = logger trace (checkFormat(msg, refs), t)
    
        def info(msg:String, refs:Any*) = logger info checkFormat(msg, refs)
    
        def info(t:Throwable, msg:String, refs:Any*) = logger info (checkFormat(msg, refs), t)
    
        def warn(msg:String, refs:Any*) = logger warn checkFormat(msg, refs)
    
        def warn(t:Throwable, msg:String, refs:Any*) = logger warn (checkFormat(msg, refs), t)
    
        def critical(msg:String, refs:Any*) = logger error checkFormat(msg, refs)
    
        def critical(t:Throwable, msg:String, refs:Any*) = logger error (checkFormat(msg, refs), t)
    
    }
    
    /**
     * Note: implementation taken from scalax.logging API
     */
    object Logging {  
    
        def loggerNameForClass(className: String) = {  
            if (className endsWith "$") className.substring(0, className.length - 1)  
            else className  
        }  
    
        def getLogger(logging: AnyRef) = LoggerFactory.getLogger(loggerNameForClass(logging.getClass.getName))  
    }
    
    0 讨论(0)
  • 2020-12-07 07:36

    With Scala 2.10+ Consider ScalaLogging by Typesafe. Uses macros to deliver a very clean API

    https://github.com/typesafehub/scala-logging

    Quoting from their wiki:

    Fortunately Scala macros can be used to make our lives easier: ScalaLogging offers the class Logger with lightweight logging methods that will be expanded to the above idiom. So all we have to write is:

    logger.debug(s"Some ${expensiveExpression} message!")
    

    After the macro has been applied, the code will have been transformed into the above described idiom.

    In addition ScalaLogging offers the trait Logging which conveniently provides a Logger instance initialized with the name of the class mixed into:

    import com.typesafe.scalalogging.slf4j.LazyLogging
    
    class MyClass extends LazyLogging {
      logger.debug("This is very convenient ;-)")
    }
    
    0 讨论(0)
  • 2020-12-07 07:38

    Logging in 2020

    I was really surprised that Scribe logging framework that I use at work isn't even mentioned here. What is more, it doesn't even appear on the first page in Google after searching "scala logging". But this page appears when googling it! So let me leave that here.

    Main advantages of Scribe:

    • it is NOT a slf4j wrapper
    • supports also Scala.js and Scala Native
    • it is really fast, check comparison here: https://www.matthicks.com/2018/02/scribe-2-fastest-jvm-logger-in-world.html
    0 讨论(0)
  • 2020-12-07 07:40

    Writer, Monoid and a Monad implementation.

    0 讨论(0)
  • 2020-12-07 07:44

    Don't use Logula

    I've actually followed the recommendation of Eugene and tried it and found out that it has a clumsy configuration and is subjected to bugs, which don't get fixed (such as this one). It doesn't look to be well maintained and it doesn't support Scala 2.10.

    Use slf4s + slf4j-simple

    Key benefits:

    • Supports latest Scala 2.10 (to date it's M7)
    • Configuration is versatile but couldn't be simpler. It's done with system properties, which you can set either by appending something like -Dorg.slf4j.simplelogger.defaultlog=trace to execution command or hardcode in your script: System.setProperty("org.slf4j.simplelogger.defaultlog", "trace"). No need to manage trashy config files!
    • Fits nicely with IDEs. For instance to set the logging level to "trace" in a specific run configuration in IDEA just go to Run/Debug Configurations and add -Dorg.slf4j.simplelogger.defaultlog=trace to VM options.
    • Easy setup: just drop in the dependencies from the bottom of this answer

    Here's what you need to be running it with Maven:

    <dependency>
      <groupId>com.weiglewilczek.slf4s</groupId>
      <artifactId>slf4s_2.9.1</artifactId>
      <version>1.0.7</version>
    </dependency>
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-simple</artifactId>
      <version>1.6.6</version>
    </dependency>
    
    0 讨论(0)
  • 2020-12-07 07:47

    This is how I got Scala Logging working for me:

    Put this in your build.sbt:

    libraryDependencies += "com.typesafe.scala-logging" %% "scala-logging" % "3.7.2",
    libraryDependencies += "ch.qos.logback" % "logback-classic" % "1.2.3"
    

    Then, after doing an sbt update, this prints out a friendly log message:

    import com.typesafe.scalalogging._
    object MyApp extends App with LazyLogging {
      logger.info("Hello there")
    }
    

    If you are using Play, you can of course simply import play.api.Logger for writing log messages: Logger.debug("Hi").

    See the docs for more info.

    0 讨论(0)
提交回复
热议问题