3 Stimmen

Problem bei der Definition einer Protokollierungseigenschaft in Scala

Es scheint, dass gemeinsame Logging-Muster in Scala ist eine Logging-Trait zu verwenden, die mit konkreten Klasse gemischt wird (vgl. Open-Source-Projekte wie Liftweb, Akka, ...).

So etwas in der Art:

trait Logging {
  val loggerName = this.getClass.getName
  @transient lazy val log = new Logger(loggerName)
}

Das ist genau das, was ich gerade verwende, aber ich stehe wegen dieses Musters vor einem Problem. In der Tat, wenn die Logging-Eigenschaft von einer Klasse gemischt wird, die abgeleitet ist, wird der Logger mit dem Namen der am meisten abgeleiteten Klasse verwendet werden.

Hier ist ein Beispiel, um mich zu verdeutlichen:

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

Wenn ich dieses Programm ausführe, erhalte ich:

[b.B] : log from A
[b.B] : log from B

Anstelle von:

[a.A] : log from A
[b.B] : log from B

Hat jemand eine Lösung für dieses Problem gefunden?

2voto

pedrofurla Punkte 12743

Diesen Effekt könnte ich mit Loggern in Begleitobjekten erreichen:

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

2voto

oxbow_lakes Punkte 131223

Ich habe die Erfahrung gemacht, dass dies mit Sicherheit nicht das Verhalten, das Sie wollen .

Wenn Sie eine Klassenhierarchie haben, die Methodenüberschreibungen enthält, könnten Ihre Protokolle voll von Zeilen sein, die wie folgt aussehen:

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

Und Sie werden sich fragen, was Beton mit welcher Service-Implementierung hatten Sie zu tun? Wenn Sie das nicht wissen, wie können Sie dann sicher sein, welcher Code-Pfad eingeschlagen wurde, um dorthin zu gelangen, wo Sie jetzt sind? Vielleicht hätte es eine 3. Erklärung geben sollen, die zwischen den beiden eingebettet ist:

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

Die Fehlersuche wäre viel einfacher, wenn die Protokolle Folgendes enthalten würden

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

Denn dann können Sie sagen sofort dass Sie den falschen Foo-Dienst verwenden

-1voto

Debilski Punkte 65106

Das mag offensichtlich sein, aber wenn Sie nicht wollen, dass die Logging Trait vererbt werden soll, könnten Sie einfach eine private Variable verwenden, anstatt einen Trait einzubauen.

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

class B extends A with Logging {
}

o

class A extends Logging {
}

class B extends A {
  override lazy val log = // ...
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X