How do I configure Logback to print out the class name
Asked Answered
P

6

27

I'm using Play 2.1. I'm using the default logger play.api.Logger. I'm confused about how it works.

In my scala code, a line in class "com.myapp.tickets" in the method "getPayment()" like this

Logger.info("getTickets")

generates a log message like this.

14:58:58.005 INFO  application play.api.LoggerLike$class info  getTickets

My application-logger.xml pattern is

%d{HH:mm:ss.SSS} %-5level %logger %class %method  %msg%n

The issue I have is that %logger tells me "application", %class tells me "play.api.LoggerLike$class and %method tells me "info". I know all of that. I of course want to avoid adding more cruft into the message itself (like the class name or method).

If I print out the call stack (%caller) then level 2 has what I want, but that does not seem a viable way to generate a log.

How do I configure it to output the application specific class and method, not the class and method of the logger itself?

Preamble answered 6/3, 2013 at 21:10 Comment(1)
logback.qos.ch/manual/layouts.html#ClassicPatternLayoutRickirickie
F
24

Logback pattern :

%d{HH:mm:ss.SSS} [%thread] %-5level %class{36}.%M %L - %msg%n

Result :

14:53:47.816 [http-bio-8080-exec-3] DEBUG  c.f.s.w.s.i.example.ExServiceImpl.getStatus 993 - blocked-->0
  • [http-bio-8080-exec-3] is the thread name

  • c.f.s.w.s.i.example is the package name

  • ExServiceImpl is the class name

  • getStatus is method name

  • 993 is the line number

Fritzfritze answered 13/11, 2013 at 9:29 Comment(2)
This doesn't really address the original problem, since this still just displays the same "play.api.LoggerLike$class" cruft.Slipcase
The same thing, it doesn't help. play.api.LoggerLike$class is displayed. %logger does display correct clusterMeticulous
A
43

%class{0} will only output the class name, so instead of:

com.something.MyClass

You'll get:

MyClass

This is how my pattern for logback normally looks:

%d{HH:mm:ss} [%thread] %-5p %class{0} - %m%n

You can also add the method and the line if you are interested by doing:

%d{HH:mm:ss} [%thread] %-5p %class{0}.%method:%L - %m%n
Ambulant answered 18/3, 2013 at 11:16 Comment(1)
Is there any way to use %class inside <fileNamePattern>?Gerund
F
24

Logback pattern :

%d{HH:mm:ss.SSS} [%thread] %-5level %class{36}.%M %L - %msg%n

Result :

14:53:47.816 [http-bio-8080-exec-3] DEBUG  c.f.s.w.s.i.example.ExServiceImpl.getStatus 993 - blocked-->0
  • [http-bio-8080-exec-3] is the thread name

  • c.f.s.w.s.i.example is the package name

  • ExServiceImpl is the class name

  • getStatus is method name

  • 993 is the line number

Fritzfritze answered 13/11, 2013 at 9:29 Comment(2)
This doesn't really address the original problem, since this still just displays the same "play.api.LoggerLike$class" cruft.Slipcase
The same thing, it doesn't help. play.api.LoggerLike$class is displayed. %logger does display correct clusterMeticulous
F
4

Old thread, but common problem. Play uses a wrapper around slf4j, which causes everything to be logged as [Logger$ALogger] or [application]. There are a few ways to log the actual class name.

Put this in your class:

private static org.slf4j.Logger logger = play.logger.underlying();

And put this in your methods:

logger.info("Your message");

Another option is to replace all of your Logger calls with this, but it will add overhead since it has to fetch the underlying object every time you want to log something:

Logger.underlying().info("Your message");
Fideliafidelio answered 2/3, 2015 at 22:10 Comment(1)
Finally, something which worked. Is there no way of doing it directly from play?Doubt
C
1

I'm not sure that it's really what you want but do you try this? :

Logger(this.getClass()).info("getTickets")

Conterminous answered 8/3, 2013 at 8:10 Comment(1)
This is close but not exactly what I was looking for. I get this 06:24:52.907 INFO com.myapp.tickets$ play.api.LoggerLike$class info getTickets So %logger gets the proper string which I am OK with. That is an improvement. But %class and %method are still getting the useless values from play. Given that %logger has the proper class, the %class is not that important and can be dropped. The %method is what is missing still. Is there a way to get the real method "getPayments" instead of "info"?Preamble
T
1

I'm in the process of abandoning the single application.log approach that Play seems to default to with its Logger. My application requires the kind-of fine grained logging and runtime adjustment of it that straight-up logback does so well when classname == Logger name. I've had pretty good success going just "old school" in my controllers like...

package controllers
import play.api._
import play.api.mvc._
import org.slf4j.LoggerFactory

object Application extends Controller {
  val log = LoggerFactory.getLogger(getClass())

  def index = Action {
    log.trace("index")
    NotFound
  }

  def hb = Action {
    log.trace("hb")
    val message = makeMessage()
    log.info(message)
    Ok(message)
  }

  def makeMessage(): String = {
    val version = "@buildsig.version@"
    val tag = "@buildsig.tag@"
    val timestamp = "@buildsig.timestamp@"
    val status = makeStatus()
    return "DM2 [Version: %s] [Build: %s] [Date: %s] [Status: %s]".format(version, tag, timestamp, status)
  }

  def makeStatus(): String = {
    // TODO: Implement datastore healthcheck
    return "TODO"
  }
}

For any developer used to slf4j/logback or log4j, this approach will seem familiar. On the other hand, I am currently struggling through start shell script from "play dist" fails to locate logger.xml in JAR file where by the start script is failing to use my conf/logger.xml that gets JARed up by the "play dist" command.

If I was just a little bit better of a Scala developer, I think the same effect can be achieved with something like a Logging trait.

Truckage answered 3/6, 2013 at 22:27 Comment(0)
S
0

Since Play's Logger wraps the underlying SLF4J calls, the logger class is always "application":

13:45:21 INFO  application: - Some message

But there is an easy way round this.

Create a trait:

import play.api.Logger

trait WithLogging {
   val logger: Logger = Logger(this.getClass())
}

And in your classes just mix in the trait:

import WithLogging

class Foobarr extends WithLogging {
   def doFoo = {
      logger.info("Im in foooo")
   }
}

Now this should be:

13:45:21 INFO  models.Foobarr: - Im in foooo
Stepper answered 20/6, 2017 at 13:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.