scala中的常见日志记录模式似乎是使用与具体类混合的Logging特征(参见Liftweb,akka等开源项目)。
类似的东西:
trait Logging {
val loggerName = this.getClass.getName
@transient lazy val log = new Logger(loggerName)
}
这正是我正确使用的知识,但由于这种模式,我遇到了问题。实际上,如果Logging特征由派生的类混合,则Logger将与最派生类的名称一起使用。
这是一个澄清自己的例子:
class Logger(logName : String){
def debug( msg : String ) { println("["+logName+"] : "+msg) }
}
trait Logging {
val loggerName = this.getClass.getName
@transient lazy val log = new Logger(loggerName)
}
package a {
class A extends Logging {
log.debug("log from A")
}
}
package b {
import a._
class B extends A with Logging {
log.debug("log from B")
}
}
object LogTest {
import b._
def main(args : Array[String]) = {
val instance = new B
}
}
当我运行这个程序时,我得到了:
[b.B] : log from A
[b.B] : log from B
而不是:
[a.A] : log from A
[b.B] : log from B
有没有人找到解决这个问题的方法?
答案 0 :(得分:2)
我可以使用伴侣对象中的记录器来实现此效果:
object A extends Logging;
class A { import A._
log.debug("log from A")
}
object B extends Logging;
class B extends A { import B._
log.debug("log from B")
}
答案 1 :(得分:2)
根据我的经验,这绝对是不是您想要的行为。
当你有一些包含方法覆盖的类层次结构时,你的日志可能会充满看起来像这样的行:
13:44:42.654 - AbstractFooService [INFO] : I have a: foo
13:44:42.656 - AbstractFooService [INFO] : I have bar-d my: foo
你会问自己,你正在处理的是什么具体的服务实现?如果您不知道,您如何确定采用哪种代码路径来获取您的位置?也许在两者之间应该有一个第三个陈述:
13:44:42.655 - SpecialFooService [INFO] : I want to baz this foo to bar
如果包含日志
,则更容易调试13:44:42.654 - DefaultFooService [INFO] : I have a: foo
13:44:42.656 - DefaultFooService [INFO] : I have bar-d my: foo
因为那时你可以告诉 你正在使用错误的foo服务
答案 2 :(得分:-1)
这可能是显而易见的,但如果您不希望继承Logging
特征,则可以简单地使用私有变量而不是混合特征。
class A {
private val log = Logger(this)
}
class B extends A with Logging {
}
或
class A extends Logging {
}
class B extends A {
override lazy val log = // ...
}