如何配置Logback以打印出类名

25

我正在使用Play 2.1。我正在使用默认的记录器play.api.Logger。我对它的工作方式感到困惑。

在我的Scala代码中,类"com.myapp.tickets"中的方法"getPayment()"的一行代码如下:

Logger.info("getTickets")

生成类似以下的日志消息。
14:58:58.005 INFO  application play.api.LoggerLike$class info  getTickets

我的 application-logger.xml 的模式是:
%d{HH:mm:ss.SSS} %-5level %logger %class %method  %msg%n

我遇到的问题是%logger告诉我"application",%class告诉我"play.api.LoggerLike$class",%method告诉我"info"。我知道所有这些。当然,我想避免在消息本身中添加更多的琐碎内容(如类名或方法)。
如果我打印出调用堆栈(%caller),那么第二级就有我想要的内容,但这似乎不是生成日志的可行方法。
我该如何配置它以输出特定于应用程序的类和方法,而不是记录器本身的类和方法?

https://logback.qos.ch/manual/layouts.html#ClassicPatternLayout - Krithick S
6个回答

42

%class{0}只会输出类名,所以代替原来的写法:

com.something.MyClass

你将获得:

MyClass

这是我通常使用的logback日志模式:

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

如果您感兴趣,也可以通过以下方式添加方法和行号:

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

有没有办法在<fileNamePattern>中使用%class? - Discipulos

23

Logback模式:

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

结果:

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] 是线程名称

  • c.f.s.w.s.i.example 是包名

  • ExServiceImpl 是类名

  • getStatus 是方法名

  • 993 是行号


2
这并没有真正解决原始问题,因为它仍然只显示相同的“play.api.LoggerLike$class”垃圾。 - Matt R
同样的事情,这并没有帮助。显示的是play.api.LoggerLike$class%logger确实显示了正确的集群。 - Capacytron

4

虽然这是一个老问题,但很常见。Play框架使用一个包装器来包装slf4j,导致所有东西都被记录为[Logger$ALogger]或[application]。有几种方法可以记录实际的类名。

请在你的类中加入以下代码:

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

并将以下代码放入您的方法中:

logger.info("Your message");

另一种选择是用下面的代码替换所有Logger调用,但这会增加开销,因为每次想要记录日志时都需要获取底层对象:

Logger.underlying().info("Your message");

最终,有些东西是有效的。没有办法直接从play中完成吗? - saurabheights

1

我不确定这是否是你想要的,但你可以尝试一下:

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


1
这很接近但不完全是我想要的。我得到了这个 06:24:52.907 INFO com.myapp.tickets$ play.api.LoggerLike$class info getTickets。所以%logger得到了我满意的正确字符串。这是一个进步。但是%class和%method仍然从play中获取无用的值。鉴于%logger有正确的类,%class并不那么重要,可以省略。%method仍然缺失。有没有办法获取真正的方法“getPayments”,而不是“info”? - user2141729

1

我正在放弃Play默认的单个application.log方法,因为我的应用程序需要更细粒度的记录和运行时调整,这正是直接使用logback时类名与Logger名称匹配所擅长的。在我的控制器中,我已经采用了“老派”的方式,效果还不错...

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

任何习惯于使用slf4j/logback或log4j的开发人员都会觉得这种方法很熟悉。另一方面,我目前正在努力解决从“play dist”启动shell脚本无法定位JAR文件中的logger.xml的问题,其中启动脚本未能使用由“play dist”命令打包的我的conf/logger.xml。
如果我是一个稍微更好的Scala开发人员,我认为可以使用类似Logging trait的东西来实现相同的效果。

0

由于Play的Logger封装了底层的SLF4J调用,因此日志记录器类始终为“application”:

13:45:21 INFO  application: - Some message

但是有一个简单的解决办法。

创建一个特征:

import play.api.Logger

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

而在你的类中只需混入该特质:

import WithLogging

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

现在应该是这样的:

13:45:21 INFO  models.Foobarr: - Im in foooo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接