[slf4j-user] When more parameters than placeholders, extra parameters are not logged

jo at durchholz.org jo at durchholz.org
Sun Feb 2 09:30:09 UTC 2025


On 25.01.25 02:38, Russ Block via slf4j-user wrote:
> With this method or any similar method,
>      public void info(String format, Object... arguments) {
>          if (isInfoEnabled()) {
>              handleArgArrayCall(Level.INFO, null, format, arguments);
>          }
>      }
> If the number of objects in 'arguments' is more than the number of 
> placeholders, {}, the extra argument objects are not logged.  Is there a 
> reason for that?

I can't answer authoritatively, but I guess it is outside the scope of 
the specification as-is.

For people using IntelliJ it is not a problem as it knows about SLF4J 
and flags log lines with extra or missing arguments.
Even better, IntelliJ will give you a refactoring option to replace
   logger.log("foo is: " + foo)
with
   logger.log("foo is: {}", foo)
It also correctly handles the case with multiple parameters, and there's 
even a hotkey for making it happen that my brain does not remember 
anymore but my fingers do.

I hope other IDEs have started offering similar functionality, but I 
don't know specifics.
IntelliJ does have some deficits, in particular its cache management if 
pretty flaky compared to Eclipse's, but I found IntelliJ's refactoring 
support such a time-save that I embraced it and never looked back, 
though other IDEs might (should, actually!) have caught up since.

> If I get into a situation where I have sent more argument objects than 
> placeholders that it should append those un-placed arguments to the end 
> of the logged string.  The intent of the developer is to have the 
> parameter logged.  Finding this out from production is not good.  What 
> is sent to be logged is important information, depending on the log level.

The knee-jerk answer to that would be "you have a bug in your code, just 
fix it".
(I believe that you want something sensible but your arguments are not 
strong enough. I.e. I'm going to strike down the arguments and 
suggesting a solution, so don't get disappointed before the end.)

> My use case is that I want to push some legacy code to start looking 
> like SLF4J so we can migrate away from the older pattern filled with 
> isLogTraceEnabled calls.

I'd assume that you had extra parameters in the legacy code as well, so 
your situation did not get worse, did it?

 > I learned of the above when I was writing > JUnit tests to see all 
the things the code would do and not do.
 >
> I feel that https://www.slf4j.org/faq.html#logging_performance is 
> telling me that, in some way, the placeholder string substitution is 
> faster than appending multiple strings together.  I understood the main 
> point of the argument as converting items to string before I needed them 
> was where the overhead was.  Keeping them as type Object reduces that 
> overhead.

Actually, while the placeholder substitution _is_ faster than a string 
append, the real advantage is this:
With logger.debug("foo is: " + foo), the + operator will be called 
before logger.debug starts, and foo.toString() and string concatenation 
happen whether logger.debug does anything with it or not.
With logger.debug("foo is: {}", foo), logger.debug will FIRST check if 
it needs to do anything, and ONLY THEN will it do string substitution.

The string substitution can actually be slightly slower than the 
concatenation, because there's the extra step of extracting the 
substitution markers and copying the text to the left and right of them. 
However, the substitution code is heavily optimized and should still be 
faster anyway in the vast majority of the cases.
This is, however, just for the do-log case. The main speedup comes from 
the no-log case doing less work.


> I understand there are Sonarqube rules and PMD to prevent me from not 
> having the correct number of argument objects.  This would help, but I 
> feel like there are still going to be misses.  Since my code is custom, 
> Sonarqube and PMD do not feel like options.
You can configure these things to report only those bugs that you are 
interested in.
The main deterrent is that the setup takes time.

Now to the promised solution, should you still need it:

You can do your own Formatter that appends any the extraneous parameters.

Caveat: Formatters do not live in SLF4J, they live in the logging 
backend - typically Logback. (SLF4J has a different and somewhat 
confusing terminology for "backend" that I don't remember.) SLF4J merely 
manages all the information needed to decide whether a log message 
should actually be output, and leaves the actual outputting to the backend.

Anyway, you'll have to dive into the code of the existing standard 
formatter, find out how it's working and how to make it append the extra 
parameters.
For Logback, you do not have to write your own backend, you can 
configure your Formatter, and even inherit from Logback's standard 
Formatter so you do not have to do a lot; however, you'll want to make 
150% sure that you do not introduce any bugs, so plan a lot of review 
(if possible) and testing. Fortunately it is more time reading docs and 
code than actual coding, so the extra effort for quality control will 
not be very noticeable.

Still, I believe the refactoring support of an IDE, if possible, will be 
easier :-)

HTH!
Jo


More information about the slf4j-user mailing list