title: Built-in string formatting vs string concatenation as logging parameter
body: <p>I'm using <a href="http://www.sonarlint.org/" rel="nofollow noreferrer">SonarLint</a> that shows me an issue in the following line.</p>
  <pre><code>LOGGER.debug(&quot;Comparing objects: &quot; + object1 + &quot; and &quot; + object2);
  </code></pre>
  <p>Side-note: The method that contains this line might get called quite often.<br/><br/>
  The description for this issue is</p>
  <blockquote>
  <p>&quot;Preconditions&quot; and logging arguments should not require evaluation
  (squid:S2629)</p>
  <p>Passing message arguments that require further evaluation into a Guava
  com.google.common.base.Preconditions check can result in a performance
  penalty. That's because whether or not they're needed, each argument
  must be resolved before the method is actually called.</p>
  <p>Similarly, passing concatenated strings into a logging method can also
  incur a needless performance hit because the concatenation will be
  performed every time the method is called, whether or not the log
  level is low enough to show the message.</p>
  <p>Instead, you should structure your code to pass static or pre-computed
  values into Preconditions conditions check and logging calls.</p>
  <p>Specifically, the built-in string formatting should be used instead of
  string concatenation, and if the message is the result of a method
  call, then Preconditions should be skipped altoghether, and the
  relevant exception should be conditionally thrown instead.</p>
  <p>Noncompliant Code Example</p>
  <pre><code>logger.log(Level.DEBUG, &quot;Something went wrong: &quot; + message);  // Noncompliant; string concatenation performed even when log level too high to show DEBUG messages
  
  LOG.error(&quot;Unable to open file &quot; + csvPath, e);  // Noncompliant
  
  Preconditions.checkState(a &gt; 0, &quot;Arg must be positive, but got &quot; + a); // Noncompliant. String concatenation performed even when a &gt; 0
  
  Preconditions.checkState(condition, formatMessage());  //Noncompliant. formatMessage() invoked regardless of condition
  
  Preconditions.checkState(condition, &quot;message: %s&quot;, formatMessage()); // Noncompliant
  </code></pre>
  <p>Compliant Solution</p>
  <pre><code>logger.log(Level.SEVERE, &quot;Something went wrong: %s&quot;, message);  // String formatting only applied if needed
  
  logger.log(Level.SEVERE, () -&gt; &quot;Something went wrong: &quot; + message); //since Java 8, we can use Supplier , which will be evaluated lazily
  
  LOG.error(&quot;Unable to open file {}&quot;, csvPath, e);
  
  if (LOG.isDebugEnabled() {   LOG.debug(&quot;Unable to open file &quot; + csvPath, e);  // this is compliant, because it will not evaluate if log level is above debug. }
  
  Preconditions.checkState(arg &gt; 0, &quot;Arg must be positive, but got %d&quot;, a);  // String formatting only applied if needed
  
  if (!condition) {   throw new IllegalStateException(formatMessage()); // formatMessage() only invoked conditionally }
  
  if (!condition) {   throw new IllegalStateException(&quot;message: &quot; + formatMessage()); }
  </code></pre>
  </blockquote>
  <p>I'm not 100% sure whether i understand this right. So why is this really an issue. Especially the part about the performance hit when using string concatenation. Because I often read that string concatenation is faster than formatting it.</p>
  <p><strong>EDIT:</strong> Maybe someone can explain me the difference between</p>
  <pre><code>LOGGER.debug(&quot;Comparing objects: &quot; + object1 + &quot; and &quot; + object2);
  </code></pre>
  <p>AND</p>
  <pre><code>LOGGER.debug(&quot;Comparing objects: {} and {}&quot;,object1, object2);
  </code></pre>
  <p>is in the background. Because I think the String will get created before it is passed to the method. Right? So for me there is no difference. But obviously I'm wrong because SonarLint is complaining about it</p>