在 scala 中定义 Logging Trait 时出现问题
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
有没有人找到这个问题的解决方案?
It seems that common logging pattern in scala is to use a Logging trait which is mixed with concrete class (cf. open source projects like Liftweb, akka, ...).
Something like that:
trait Logging {
val loggerName = this.getClass.getName
@transient lazy val log = new Logger(loggerName)
}
This is exactly what I'm using right know, but I'm stuck with a problem because of this pattern. Indeed if the Logging trait is mixed by a class that is derived, the Logger will be used with the name of the most derived class.
Here is an example to clarify myself:
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
}
}
When I run this program I got:
[b.B] : log from A
[b.B] : log from B
Instead of:
[a.A] : log from A
[b.B] : log from B
Has anyone found a solution to this problem ?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我可以使用伴随对象中的记录器来实现这种效果:
I could achieve this effect using loggers in companion objects:
根据我的经验,这绝对不是您想要的行为。
当您有一些包含方法重写的类层次结构时,您的日志可能充满如下行:
您会问自己您正在处理什么具体服务实现?如果您不知道,您如何确定采用什么代码路径来到达您所在的位置?也许应该有第三条语句位于两者之间:
如果包含日志,则调试起来会更容易
因为这样你就可以立即告诉你正在使用错误的 foo 服务
It is my experience that this is most definitely not the behaviour that you want.
When you have some class hierarchy which contains method overriding, your logs might be full of lines which look like:
And you will be asking yourself what concrete service implementation were you dealing with? If you don't know, how can you be sure what code path was taken to get where you are? Maybe there should have been a 3rd statement nestling inbetween the two:
Much easier to debug if the logs contained
Because then you can tell immediately that you are using the wrong foo service
这可能是显而易见的,但如果您不希望继承 Logging 特征,则可以简单地使用私有变量而不是混合特征。
或者
This might be obvious, but if you don’t want the
Logging
trait to be inherited, you could simply use a private variable instead of mixing in a trait.or