1

Migrating from Groovy to Scala here. So far I really like Scala, however I am instantly missing my @Slf4j annotation, where I could just have:

@Slf4j
class Fizz {
    void doSomething() {
      log.info("We're doing something now...")
    }
}

...and Groovy would create an SLF4J logger and inject it into Fizz's bytecode for me. It spared me from having to do the following in every single class:

class Fizz {
    Logger log = LoggerFactory.getLogger(Fizz)

    void doSomething() {
      log.info("We're doing something now...")
    }
}

I really miss this so far.

I'm wondering if I can use traits/mixins to do the same, but it would have to be generic so I could use it with any class:

trait MyLogger[T] {
    def log = Logger.getLogger(T)
}

Then:

class Fizz extends MyLogger[Fizz] {
  def doSomething() : Unit = {
    log.info("Doing something now...")
  }
}

etc. Is this possible to do? If so, am I close or way off base here?

smeeb
  • 22,487
  • 41
  • 197
  • 389
  • It could be implemented by [macro annotation](http://docs.scala-lang.org/overviews/macros/annotations.html) – jilen Mar 12 '17 at 13:47
  • Alternatively `lazy val log = LoggerFactory.getLogger(getClass.getName)` would spare you the need to pass a type parameter. – Mateusz Kubuszok Mar 12 '17 at 14:16

1 Answers1

4

Actually, you're on the right track with your trait:

trait Logging {
  lazy val log = Logger.getLogger(getClass.getName)
}

You use it like this:

class MyStuff extends MySuperClass with Logging {
  log.info("Setting up my stuff")
}

In fact, this is pretty much what scala-logging does - plus a few more macros to save you typing the if (log.is_LEVEL_Enabled) log._LEVEL_ (but still putting it in the final output).

Sean Vieira
  • 140,251
  • 31
  • 286
  • 277