lundi 27 mai 2019

Dynamically choose implementation of logger in Scala

I have a library in which I use log4j to log things. For some particular classes of my library (all classes extending Component) I want that the log statement contain the suffix [component_name] at the beginning.

I don't want to mutate how a log statement usually looks like. Therefore, within one of these special component named 'foo' the statement log.info("message") should output [foo] message in the logging system.

This is what I did so far and where I am stuck:

object Logging {
   val logger = Logger.getLogger("my_logger_name")
}

This is the basic logger, which I call all over the code using Logging.logger.info("message")

I thought the best thing to do would be to build the enriched logger using a trait

trait WithEnrichedLogger {
   this: Component =>
   val logger = new EnrichedLogger(this.name)
}

class EnrichedLogger(name: String) {
   def info(msg: String): Unit = Logging.logger.info(s"[${name}] $msg")
}

and my component simply looks like

abstract class Component with WithEnrichedLogger {
     def name: String
     ....

     def some_method: Unit = { 
        logger.info("log statement") \\ it should print the '[name]' at the beginning 
     }
 } 

The problem in this setup is that at the moment of Component creation, the WithEnrichedLogger trait gets initialised and the value of name is still null. For this reason, the statement is "null log statement"

This solution looked to me the most elegant one, but please propose me different ones if better

Aucun commentaire:

Enregistrer un commentaire