54

I'd like to format my doubles and floats to a certain number of decimal places with SLF4J.

Basically, I'm looking for the equivalent of Java's String.format("%.2f", floatValue) in SLF4J.

Having read through SLF4J's documentation and googling around I couldn't find a hint whether it has that feature.

I'm using slf4j-api:1.7.6 and slf4j-jdk14:1.7.6

Any help is much appreciated.

Matthias Braun
  • 32,039
  • 22
  • 142
  • 171
  • 6
    This is really a work-around, not an answer, so I'll add it as a comment: You could just pass the output of `String.format` as the argument in your logger call: `logger.debug("floatValue is {}", String.format("%.2f", floatValue));` – daiscog Feb 03 '15 at 17:59
  • 8
    This defeats the purpose of SLF4Js parameterized logging, which is avoiding evaluation in the case when log messages are not emitted. – Todd Freed Aug 24 '15 at 21:45
  • In this case, it'd be quickest to wrap the call in `if (logger.isDebugEnabled()) logger.debug(... calls to String.format ....);` to avoid the whole mess. – Ti Strga Sep 29 '15 at 17:56
  • @ToddFreed You’d be avoiding the string concatenation of the message, which would take away some of the overhead. – Alf Nov 27 '15 at 14:53

2 Answers2

36

I am assuming that you're referring to SLF4J's convention of expanding parameters, e.g.:

float f;
...
logger.debug("My number is {}", f);

So, the answer is no. As of SLF4J 1.7.7, what you're asking to do is impossible as SLF4J's expansion algorithm doesn't allow for custom renderers (such as the one available via Log4J).

Seems worthy of a feature request, though.

EDIT:

Well, {} is "only supported" for performance considerations, current formatting implementation outperforms String.format() at 10 times. http://www.slf4j.org/faq.html#logging_performance so it's unlikely to change

(source)

Tombart
  • 30,520
  • 16
  • 123
  • 136
Isaac
  • 16,458
  • 5
  • 57
  • 81
29

A somewhat ugly solution that incurs the creation of a temporary object could be this

public class DelayedFormatter {
    public static Object format(String format, Object... args) {
        return new Object() {
            @Override
            public String toString() {
                return String.format(format, args);
            }
        };
    }
}

and then

import static DelayedFormatter.format;
...
logger.debug("v = {}", format("%.03f", v));
Stefan Frye
  • 2,007
  • 1
  • 20
  • 24
Svullo
  • 421
  • 5
  • 5
  • 5
    elegant approach – sofend Jan 01 '18 at 01:41
  • Most of the time you'll be logging primitive values, and that incurs the creation of a temporary (wrapper) object anyway... OTOH String#Format() should be avoided. – Flávio Etrusco Jun 24 '21 at 12:17
  • You can of course make the DelayedFormatter your wrapper (so it's just one object created) if you add methods for primitives like format(String format, double arg){...toString(){ return String.format(format, arg); } – Svullo Oct 09 '21 at 14:11