Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unable to understand why to use parameterized logging

I was reading upon parameterized logging in Java, it is said to use parameterized logging instead of concatenation as it performs lazy evaluation.

So instead of

logger.debug("My text is" + x);

use:

logger.debug("My text is {}", x);

If the trace level is set to only info logs, why does the concatenation happen in the first scenario?

Also if I have a time consuming function in log, it is said to use:

logger.debug("My text is {}", () -> compute());

instead of

logger.debug("My text is {}", compute());

In this case, why is the lambda method considered a better approach. Won't compute also be called lazily like in the string concatenation case?

like image 862
user1692342 Avatar asked Dec 06 '22 13:12

user1692342


2 Answers

Before you enter logger.debug() the parameters must be calculated.

In the first case, you always get String concatenation before passing the resulting String to the method (which may not use it). With the parameterized version no concatenation is done, the x is passed in and may be used or not.

Same deal with compute(). The non-lambda version will always execute compute() before entering the method, because it will need the result of compute() in order to invoke the method.

The lambda version will pass the method (actually a Supplier which runs the method when the result is requested) as a parameter instead of the method result, and it will only be executed if needed.

like image 111
Kayaman Avatar answered Dec 26 '22 21:12

Kayaman


The idea is the simple. Usually, applications use logger very frequently, but logging itself is resource-consuming operation, at least because you need to write something to hard drive. Looking at your example:

logger.debug("My text is " + x);

Let's imagine that INFO level turned on in the logger configuration. Then the code executes this line, it needs to evaluate parameter to pass in debug function, so it does. But inside debug logger will check which log level turned on and it will be INFO. The message you want should not be logged in this case, so the calculations required to assembly the parameter string will be considered as waste of time. To overcome such problems you can check if the log level turned before calling method, like this

if (logger.isDebugEnabled()) {
    logger.debug("My text is " + x)
}

It will be better, because you will assemble message only it's required, but the problem here is that logger.isDebugEnabled() evaluated twice. First inside your code and then inside logger.debug(). That's why parametrized logging suggested, because it left both these problems behind. The same applicable for time-consuming operations where lambdas suggested. Hope it helps and a bit clear for you now!

like image 20
Sergey Prokofiev Avatar answered Dec 26 '22 20:12

Sergey Prokofiev