Logging in Scala

2019-01-16 00:02发布

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 unobtrusive. Here's a basic requirement list:

  • simple
  • does not clutter the code. Scala is great for its brevity. I don't want half of my code to be logging statements
  • log format can be changed to fit the rest of my enterprise logs and monitoring software
  • supports levels of logging (ie debug, trace, error)
  • can log to disk as well as other destinations (i.e. socket, console, etc.)
  • minimum configuration, if any
  • works in containers (ie, web server)
  • (optional, but nice to have) comes either as part of the language or as a maven artifact, so I don't have to hack my builds to use it

I know I can use the existing Java logging solutions, but they fail on at least two of the above, namely clutter and configuration.

Thanks for your replies.

标签: logging scala
13条回答
神经病院院长
2楼-- · 2019-01-16 00:48

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))
查看更多
登录 后发表回答