문제

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 ?

도움이 되었습니까?

해결책

I could achieve this effect using loggers in companion objects:

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")
}

다른 팁

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:

13:44:42.654 - AbstractFooService [INFO] : I have a: foo
13:44:42.656 - AbstractFooService [INFO] : I have bar-d my: foo

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:

13:44:42.655 - SpecialFooService [INFO] : I want to baz this foo to bar

Much easier to debug if the logs contained

13:44:42.654 - DefaultFooService [INFO] : I have a: foo
13:44:42.656 - DefaultFooService [INFO] : I have bar-d my: foo

Because then you can tell immediately that you are using the wrong foo service

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.

class A {
  private val log = Logger(this)
}

class B extends A with Logging {
}

or

class A extends Logging {
}

class B extends A {
  override lazy val log = // ...
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top