logback 不打印方法或行号

logback doesn't print method or line number

这是一个 Gradle 项目,使用 Groovy 作为应用程序代码和测试代码。但是我正在使用 logback.xml 文件进行配置。

这里可能重要的一个因素是我使用 Groovy @Slf4j 注释来提供记录器。

%method%line 转换词通常分别打印为 "invoke" 和“-1”(尽管有时 "invoke0" 和“-2”)。

有趣的是,它有时会打印方法和编号:例如当它是带有 Exception 参数的 ERROR 级别日志时:

log.error( 'indexSearcher.indexReader.close() threw Exception', e )

...我认为这与携带它的 e 对象有关 "location" 数据,然后 logback 可以利用这些数据。但偶尔会打印一条 INFO 级别的消息,其中包含方法和行号:这很令人费解。

我见过有人对异步附加程序有问题,但我的附加程序是 ROLLING_FILE (RollingFileAppender)。这不是异步附加程序的扩展。

我尝试了其他 SO 问题中记录的其他补救措施(例如 here):我已将这些行添加到我的附加程序中:

<includeCallerData>true</includeCallerData>
<param name="locationInfo" value="true" />

...没有解决问题

某处有人说有必要确保在某些时候打开调试数据。在 Groovy 的情况下,我不确定如何尝试这个想法。

logback.groovy

appender("STDOUT", ConsoleAppender) {
  encoder(PatternLayoutEncoder) {
    pattern = "%d{HH:mm:ss.SSS} [%thread] %-5level {%logger} - %class.%method:%line - %msg%n"
  }
}
root(DEBUG, ["STDOUT"])

X.groovy

@GrabConfig(systemClassLoader=true)
@GrabResolver(name='maven2',root='http://repo1.maven.org/maven2/')
@Grab(group='ch.qos.logback', module='logback-classic', version='1.2.3')
@Grab(group='org.slf4j', module='slf4j-api', version='1.7.30')

import groovy.util.logging.Slf4j

@Slf4j
class A {
    def f() {
        log.info 'msg-info-2'       //line 11
        log.with{
            info  'msg-info-1'      //line 13
            //new Exception("test").printStackTrace(System.out)
        }
    }
}

def a = new A()
a.f()

命令 groovy X.groovy 打印:

12:24:43.134 [main] INFO  {A} - A.f:11 - msg-info-1
12:24:43.139 [main] INFO  {A} - sun.reflect.NativeMethodAccessorImpl.invoke0:-2 - msg-info-2

为什么

在 logback 中有一个 class CallerData 方法 extract 提取调用者数据信息作为基于 Throwable 参数和 returns 的数组StackTraceElement 的数组。它试图清除堆栈跟踪,但是对于 groovy 它可能真的很复杂。

例如,如果您取消注释行 new Exception("test").printStackTrace(System.out)

您会看到这样的堆栈跟踪:

java.lang.Exception: test
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    ... + 11 elements
    at A$_f_closure1.doCall(X.groovy:14)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    ... + 15 elements
    at A.f(X.groovy:12)
    ... + 20 elements

CallerData 尝试跳过堆栈跟踪中的技术 groovy 元素,但未能检测到正确的元素。


解决方案

可以修改 logback 上下文的 Framework Packages

我不知道如何从 logback.xml 做到这一点,但我找到了如何使用 logback.groovy

做到这一点

logback.groovy(修改)

也许对于你的情况你必须添加另一个框架(忽略)包...

context.getFrameworkPackages().addAll([
    "sun.reflect", 
    "java.lang.reflect", 
    "org.codehaus.groovy", 
    "groovy.lang.MetaMethod",
    "jdk.internal.reflect"
    ])

appender("STDOUT", ConsoleAppender) {
  encoder(PatternLayoutEncoder) {
    pattern = "%d{HH:mm:ss.SSS} [%thread] %-5level {%logger} - %class.%method:%line - %msg%n"
  }
}
root(DEBUG, ["STDOUT"])

使用此配置,上面的代码可以正确打印行:

13:12:14.410 [main] INFO  {A} - A.f:11 - msg-info-2
13:12:14.416 [main] INFO  {A} - A$_f_closure1.doCall:13 - msg-info-1