This.getClass usage in Scala traits

Can someone explain why this code works this way? I wanted to do my own Loggable trait proof of concept. The plan was to instantiate the log instance so that inherited classes couldn't do the job. But as I can see, this is not what I wanted.

Here is the code:

package hu.jonas.simple

trait Loggable {
  val logger = java.util.logging.Logger.getLogger(this.getClass.getName)

  def whoAmI = {
    logger.info(this.getClass.getName)
  }
}

class Service extends Loggable {
  def answer = {
    whoAmI
  }
}

object Main extends App {
  new Service().answer
}

      

The following log message appeared:

Jan 25, 2013 2:02:07 PM hu.jonas.simple.Loggable$class whoAmI
INFO: hu.jonas.simple.Service

      

Why are the two this.getClass.getName different? And more than that, what I need to write when I instantiate the logger to get this:

Jan 25, 2013 2:02:07 PM hu.jonas.simple.Service whoAmI
INFO: hu.jonas.simple.Service

      

+3


source to share


2 answers


In your code, both occurrences getClass.getName

return the same value. But the logger, when formatting the output message, just uses the original class (which it might know by checking the stack) instead of the log name (which in your case matches getClass.getName

). Thus, the logger, when displaying the header for the log entry, actually uses the name of the class in which the call is made log

, and the content of the log message is the name of the execution class of the instance. So it looks like a static vtime type problem. If you're wondering where it comes from Loggable$class

, it so happens that the method implementations in the named attribute are T

located in the named JVM class T$class

.

Now, for illustration. In the code below, I change the log handler to erase the information from the original class. This forces the registrar to use the registrar name instead of the original class name and returns the expected behavior.



import java.util.logging._
trait Loggable {
  val logger = Logger.getLogger(this.getClass.getName)

  logger.getParent.getHandlers.foreach{ handler => 
    val formatter = handler.getFormatter
    handler.setFormatter( new java.util.logging.Formatter {
      def format( record: LogRecord ) = {
        record.setSourceClassName( null )
        formatter.format( record )
      }
    })
  }


  def whoAmI = {
    logger.info(this.getClass.getName)
  }
}

class Service extends Loggable {
  def answer = {
    whoAmI
  }
}

object Main extends App {
  new Service().answer
}

      

Now, to correct your problem correctly, there is a property named java.util.logging.SimpleFormatter.format

that you can set to change the default log formatting. Use it to make the log use the logger name instead of the original one. See http://docs.oracle.com/javase/7/docs/api/index.html?java/util/logging/SimpleFormatter.html . Please note that this requires Java 7.

+3


source


What you are looking at is a method called a logger, not necessarily a log class. In your case, it is Loggable.whoAmI

. The class created is of type hu.jonas.simple.Service

, but since the method is on Loggable

, this is what is displayed. This information is usually retrieved by looking at the stack trace.

In the example below, you'll get the same results by pulling on the stack trace:

trait Loggable { 
  val logger = java.util.logging.Logger.getLogger(this.getClass.getName)

  def whoAmI = {
    val stackTrace = Thread.currentThread.getStackTrace();
    logger.info("Class: %s, Method: %s".format(stackTrace(1).getClassName, 
      stackTrace(1).getMethodName))
    logger.info(this.getClass.getName)
  }
}

      

This will give the result:



Jan 25, 2013 9:39:28 AM $line99.$read$$iw$$iw$Loggable$class whoAmI
INFO: Class: $line99.$read$$iw$$iw$Loggable$class, Method: whoAmI

Jan 25, 2013 9:39:28 AM $line99.$read$$iw$$iw$Loggable$class whoAmI
INFO: $line100.$read$$iw$$iw$Service

      

What you see is consistent with what the Logger shows. If you keep going down the stack, you will see that you can get into the call hierarchy with stackTrace(3)

, resulting in:

Jan 25, 2013 9:43:58 AM $line107.$read$$iw$$iw$Loggable$class whoAmI
INFO: Class: $line108.$read$$iw$$iw$Service, Method: answer

      

I don't know exactly how to change this using java.util.Logger

, but as pointed out in the other answer, perhaps using a formatter you can get the desired output. Otherwise, you can try a different logging mechanism, or roll your information above.

0


source







All Articles