Built-in string formatting vs string concatenation as logging parameter

前端 未结 4 1940
野性不改
野性不改 2021-01-01 10:42

I\'m using SonarLint that shows me an issue in the following line.

LOGGER.debug(\"Comparing objects: \" + object1 + \" and \" + object2);

S

相关标签:
4条回答
  • 2021-01-01 10:53

    First let's understand the problem, then talk about solutions.

    We can make it simple, assume the following example

    LOGGER.debug("User name is " + userName + " and his email is " + email );
    

    The above logging message string consists of 4 parts
    And will require 3 String concatenations to be constructed.

    Now, let's go to what is the issue of this logging statement.

    Assume our logging level is OFF, which means that we don't interested in logging now.

    We can imagine that the String concatenations (slow operation) will be ALWAYS applied and will not consider the logging level.

    Wow, after understanding the performance issue, let's talk about the best practice.

    Solution 1 (NOT optimal)
    Instead of using String concatenations, we can use String Builder

    StringBuilder loggingMsgStringBuilder = new StringBuilder();
    loggingMsgStringBuilder.append("User name is ");
    loggingMsgStringBuilder.append(userName);
    loggingMsgStringBuilder.append(" and his email is ");
    loggingMsgStringBuilder.append(email );
    LOGGER.debug(loggingMsgStringBuilder.toString());
    

    Solution 2 (optimal)
    We don't need to construct the logging message before check the debugging level.
    So we can pass logging message format and all parts as parameters to the LOGGING engine, then delegate String concatenations operations to it, and according to the logging level, the engine will decide to concatenate or not.

    So, It's recommended to use parameterized logging as the following example

    LOGGER.debug("User name is {} and his email is {}", userName, email);
    
    0 讨论(0)
  • 2021-01-01 11:08

    Consider the below logging statement :

    LOGGER.debug("Comparing objects: " + object1 + " and " + object2);
    

    what is this 'debug' ?

    This is the level of logging statement and not level of the LOGGER. See, there are 2 levels :

    a) one of the logging statement (which is debug here) :

    "Comparing objects: " + object1 + " and " + object2
    

    b) One is level of the LOGGER. So, what is the level of LOGGER object : This also must be defined in the code or in some xml , else it takes level from it's ancestor .

    Now why am I telling all this ?

    Now the logging statement will be printed (or in more technical term send to its 'appender') if and only if :

    Level of logging statement >= Level of LOGGER defined/obtained from somewhere in the code
    

    Possible values of a Level can be

    DEBUG < INFO <  WARN < ERROR
    

    (There can be few more depending on logging framework)

    Now lets come back to question :

    "Comparing objects: " + object1 + " and " + object2
    

    will always lead to creation of string even if we find that 'level rule' explained above fails.

    However,

    LOGGER.debug("Comparing objects: {} and {}",object1, object2);
    

    will only result in string formation if 'level rule explained above' satisfies.

    So which is more smarter ?

    Consult this url.

    0 讨论(0)
  • String concatenation means LOGGER.info("The program started at " + new Date());

    Built in formatting of logger means
    LOGGER.info("The program started at {}", new Date());

    very good article to understand the difference http://dba-presents.com/index.php/jvm/java/120-use-the-built-in-formatting-to-construct-this-argument

    0 讨论(0)
  • 2021-01-01 11:19

    I believe you have your answer there.

    Concatenation is calculated beforehand the condition check. So if you call your logging framework 10K times conditionally and all of them evaluates to false, you will be concatenating 10K times with no reason.

    Also check this topic. And check Icaro's answer's comments.

    Take a look to StringBuilder too.

    0 讨论(0)
提交回复
热议问题