This is in a Gradle project using Groovy for the app code as well as test code. But I\'m using a logback.xml file for configuration.
One factor here that may be signific
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()
The command groovy X.groovy prints:
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
why
in logback there is a class CallerData with method extract that extracts caller data information as an array based on a Throwable parameter and returns an array of StackTraceElement. It tries to cleenup the stacktrace, however for groovy it could be really complex.
For example if you uncomment the line new Exception("test").printStackTrace(System.out)
You'll see stacktrace like this:
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 tries to skip the technical groovy elements from stacktrace but fails to detect the right one.
solution
It's possible to modify the Framework Packages for the logback context.
I don't know how to do that from logback.xml, but I found how to do it using logback.groovy
logback.groovy (modified)
maybe for your case you have to add another framework (ignored) packages...
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"])
with this configuration the code above prints lines correctly:
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