使用Scala中的简单表达式链接日志记录

时间:2012-08-06 21:05:42

标签: scala logging slf4j

我通常通过LiftWeb中的Loggable包装器将Scala与SLF4J一起使用。除了仅由 1表达式链构成的非常常见的方法外,这种方法效果很好。

因此,如果您想将记录添加到这样的方法,那么简单漂亮,没有大括号

def method1():Z = a.doX(x).doY(y).doZ()

必须成为:

def method1():Z = {
  val v = a.doX(x).doY(y).doZ()
  logger.info("the value is %s".format(v))
  v
}

不太一样,是吗?我试着用它来解决它:

class ChainableLoggable[T](val v:T){
  def logInfo(logger:Logger, msg:String, other:Any*):T = {
    logger.info(msg.format(v, other))
    v
  }
}
implicit def anyToChainableLogger[T](v:T):ChainableLoggable[T] = new ChainableLoggable(v)

现在我可以使用更简单的表格

 def method1():Z = a.doX(x).doY(y).doZ() logInfo(logger, "the value is %s") 

然而,1个额外的对象实例化和来自Any的隐式开始看起来像代码发臭。

有谁知道更好的解决方案?或许我甚至不应该为此烦恼?

3 个答案:

答案 0 :(得分:2)

这看起来是正确的方法,特别是如果你没有隐含的抽头(不在标准库中,但是这样的东西被广泛使用 - 并且tap是标准的红宝石):

class TapAnything[A](a: A) {
  def tap(f: A => Any): A = { f(a); a }
}
implicit def anything_can_be_tapped[A](a: A) = new TapAnything(a)

有了这个,将信息隐含在自己的内容就不那么重要了,但如果你使用它,那就是对

的改进了。
.tap(v => logger.info("the value is %s".format(v)))

答案 1 :(得分:2)

Scala 2.10只为您提供了一个解决方案 - 这是一个新功能Value Class,它允许您获得与隐式包装器提供的相同的效果,但没有来自实例化这些包装类的开销。要应用它,您必须像这样重写代码:

implicit class ChainableLoggable[T](val v : T) extends AnyVal {
  def logInfo(logger:Logger, msg:String, other:Any*) : T = {
    logger.info(msg.format(v, other))
    v
  }
}

编译器会将logInfo转换为Java的常用“util”静态方法的类比,方法是将v : T添加到它的参数列表中并相应地更新它的用法 - 看,没有任何实例化。

答案 2 :(得分:0)

如果您想避免使用implicits,可以在自己的日志记录特征中定义类似这样的函数。可能不如带有隐含的解决方案那么漂亮。

def info[A](a:A)(message:A=>String) = {
  logger.info(message(a))
  a
}

info(a.doX(x).doY(y).doZ())("the value is " + _)