Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why Logback/Slf4j logs wrong file and line numbers in Groovy?

I have noticed that sometimes Logback/Slf4j logs wrong file and line numbers in Groovy.

I have a lot of bad file/line number logs in my Grails application (more than 50% of all logs)

Is there any workaround?

Simplest example:

logback.groovy

appender("STDOUT", ConsoleAppender) {
    encoder(PatternLayoutEncoder) {
        pattern = '%d{HH:mm:ss.SSS} [%-5level] %msg \\(%file:%line\\)%n'
    }
}

root(DEBUG, ["STDOUT"])

Test.groovy

@Slf4j
class Test {
    static void main(String[] args) {
        log.info("${'Wrong file and line number!'}")
    }
}

Output

23:24:23.894 [INFO ] 0 Wrong file and line number! (NativeMethodAccessorImpl.java:-2)

Example of my grails log output with problem

10:16:44.881 [DEBUG] [org.grails.plugin.resource.ResourceProcessor] -------------------------------------------------- (null:-1)
like image 829
Michal Z m u d a Avatar asked Nov 11 '13 22:11

Michal Z m u d a


People also ask

Which file is used by Logback logging system?

To create a configuration for Logback, you can use XML as well as Groovy. The system will automatically pick up and use the configuration automatically, as long as you're adhering to the naming convention. There are three valid standard file names you can choose from: logback-test.

What is Appender in Logback?

Appenders place log messages in their final destinations. A Logger can have more than one Appender. We generally think of Appenders as being attached to text files, but Logback is much more potent than that. Layout prepares messages for outputting.

Why do we use Logback XML?

Logback executes an async appender in a separate thread to decouple the logging overhead from the thread executing your code. Using the async appender is incredibly easy. Refer the appender that should be asynchronously invoked within an <appender> element.


1 Answers

The problem occurs when a GString is logged (any normal String logs the correct line number). I have no clue why it works like this but I have found two workarounds: Either convert GString to String by calling the toString() method (ugly) or use template format with parameters

import groovy.util.logging.Slf4j;

@Slf4j
class Test {
    static void main(String[] args) {
        def x = 1
        log.info("Does not work: ${x}")
        log.info("Works ${x}".toString())
        log.info("Works {}", x)
    }
}
like image 97
Gergely Toth Avatar answered Oct 23 '22 11:10

Gergely Toth