Logging in Scala

前端 未结 14 2026
南旧
南旧 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:22

    I find very convenient using some kind of java logger, sl4j for example, with simple scala wrapper, which brings me such syntax

    val #! = new Logger(..) // somewhere deep in dsl.logging.
    
    object User with dsl.logging {
    
      #! ! "info message"
      #! dbg "debug message"
      #! trace "var a=true"
    
    }
    

    In my opinion very usefull mixin of java proven logging frameworks and scala's fancy syntax.

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

    Using slf4j and a wrapper is nice but the use of it's built in interpolation breaks down when you have more than two values to interpolate, since then you need to create an Array of values to interpolate.

    A more Scala like solution is to use a thunk or cluster to delay the concatenation of the error message. A good example of this is Lift's logger

    Log.scala Slf4jLog.scala

    Which looks like this:

    class Log4JLogger(val logger: Logger) extends LiftLogger {
      override def trace(msg: => AnyRef) = if (isTraceEnabled) logger.trace(msg)
    }
    

    Note that msg is a call-by-name and won't be evaluated unless isTraceEnabled is true so there's no cost in generating a nice message string. This works around the slf4j's interpolation mechanism which requires parsing the error message. With this model, you can interpolate any number of values into the error message.

    If you have a separate trait that mixes this Log4JLogger into your class, then you can do

    trace("The foobar from " + a + " doesn't match the foobar from " +
          b + " and you should reset the baz from " + c")
    

    instead of

    info("The foobar from {0} doesn't match the foobar from {1} and you should reset the baz from {c},
         Array(a, b, c))
    
    0 讨论(0)
  • 2020-12-07 07:26

    slf4j wrappers

    Most of Scala's logging libraries have been some wrappers around a Java logging framework (slf4j, log4j etc), but as of March 2015, the surviving log libraries are all slf4j. These log libraries provide some sort of log object to which you can call info(...), debug(...), etc. I'm not a big fan of slf4j, but it now seems to be the predominant logging framework. Here's the description of SLF4J:

    The Simple Logging Facade for Java or (SLF4J) serves as a simple facade or abstraction for various logging frameworks, e.g. java.util.logging, log4j and logback, allowing the end user to plug in the desired logging framework at deployment time.

    The ability to change underlying log library at deployment time brings in unique characteristic to the entire slf4j family of loggers, which you need to be aware of:

    1. classpath as configuration approach. The way slf4j knows which underlying logging library you are using is by loading a class by some name. I've had issues in which slf4j not recognizing my logger when classloader was customized.
    2. Because the simple facade tries to be the common denominator, it's limited only to actual log calls. In other words, the configuration cannot be done via the code.

    In a large project, it could actually be convenient to be able to control the logging behavior of transitive dependencies if everyone used slf4j.

    Scala Logging

    Scala Logging is written by Heiko Seeberger as a successor to his slf4s. It uses macro to expand calls into if expression to avoid potentially expensive log call.

    Scala Logging is a convenient and performant logging library wrapping logging libraries like SLF4J and potentially others.

    Historical loggers

    • Logula, a Log4J wrapper written by Coda Hale. Used to like this one, but now it's abandoned.
    • configgy, a java.util.logging wrapper that used to be popular in the earlier days of Scala. Now abandoned.
    0 讨论(0)
  • 2020-12-07 07:27

    After using slf4s and logula for a while, I wrote loglady, a simple logging trait wrapping slf4j.

    It offers an API similar to that of Python's logging library, which makes the common cases (basic string, simple formatting) trivial and avoids formatting boilerplate.

    http://github.com/dln/loglady/

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

    I use SLF4J + Logback classic and apply it like this:

    trait Logging {
      lazy val logger = LoggerFactory.getLogger(getClass)
    
      implicit def logging2Logger(anything: Logging): Logger = anything.logger
    }
    

    Then you can use it whichever fits your style better:

    class X with Logging {
        logger.debug("foo")
        debug("bar")
    }
    

    but this approach of course uses a logger instance per class instance.

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

    Haven't tried it yet, but Configgy looks promising for both configuration and logging:

    http://github.com/robey/configgy/tree/master

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