[slf4j-user] Varargs for Logger methods

Ceki Gülcü listid at qos.ch
Fri Feb 17 11:36:46 CET 2006


At 10:40 AM 2/17/2006, Ceki Gülcü wrote:
>At 12:55 AM 2/17/2006, Kostis Anagnostopoulos wrote:
>>On 2/16/06, Ceki Gülcü <listid at qos.ch> wrote:
>> > ...
>> > Oh, OK. I was thinking of replacing
>> >
>> > public interface Logger {
>> >
>> >   void debug(String msg);
>> >   void debug(String msg, Object o);
>> >   void debug(String msg, Object o1, Object o2);
>> >   void debug(String msg, Object[] oArray);
>> >   ....
>> > }
>> >
>> > by the more economical
>> >
>> > public interface Logger {
>> >   void debug(String msg, Object ... args);
>> >   ....
>> > }
>> >
>> > But the above is not what you had in mind.
>>
>>I hadn't thought out all the details of my suggestion.
>>Of course i agree with the class you describe!

I would not want to split hairs but you should not agree with the changes 
described in the second Logger interface shown above. :-)

Why? Because, when the four methods in the first class et replaced by a 
single varargs method, then client classes compiled against the first 
Logger interface will not *run* with the second Logger interface although 
the same client class will *compile* unmodified against the second version 
of the Logger interface. Since the beginning of this discussion I've been 
trying to emphasize that compile time compatibility does not guarantee run 
time compatibility. (You may have been already aware of this point. If that 
is the case, please forgive the incessant repetition.)

[snip]

>> > In a few years time when JDK 1.5 gains wider deployment share, we can
>> > revisit the issue.
>>
>>Well, there is something that we can get prepared from now:

:-)

>>What would the method would look like, when using exceptions
>>AND params together?
>>Would it be like:
>>
>>     void debug(String msg, Throwable t, Object... params);
>>
>>then we woule separate the 'msg' argument from the correlated 'params'
>>with the exeception, and that is confusing (does the exception
>>participate in the substitution, or not?).

Good point. Currently, the Logger interface does not support parameterized 
logs with exceptions. The user has to choose between logging an exception 
and logging a parameterized message but not both. If you need to log a 
parameterized message *and* an exception, you can do it in two steps.

logger.error("While discretely fiddling with nose an exception was thrown", 
etiquetteException);
logger.error("Incriminated finger: {}", myIndex);


>>I suggest the next forms to solve the confusion:
>>
>>     void debug(Throwable t, String msg, Object... params);
>>     void debug(Throwable t);
>>     void debug(String msg);
>>
>>While this form looks weird, it only has 1 problem:
>>Incompatible "look'n feel" with other APIs

I am not keen on adding debug(Throwable, String, Object...) to the logger 
interface for two reasons.

1) In my opinion the parameterized+exception log can be broken in two two 
separate log messages.
2) I would like to avoid adding yet another overloaded printing method to 
the Logger interface. Each new signature means 8 (=4*2) new methods. There 
are 4 levels and for each level there are methods with and without markers.

>>But it has 2 more merits:
>>* First, an exception can be placed as a 'param' without the cast to 
>>(Object),
>>like next (more natural) form:
>>
>>     debug("Problems due to: {}!", ex);
>>instead of:
>>     debug("Problems due to: {}!", (Object)ex);
>>
>>* Second, since msgs some time are wide, when using the current form,
>>we cannot see easily whether the exception is included in the log
>>(it's too far on the right).
>>The next would be a nice example (only if mail-middleman did not wrap
>>long lines):
>>
>>     try {
>>         ....
>>     } catch(SomeException ex) {
>>         getLogger().debug("I'm not sure whether to include the
>>exception stack at the end of this message", ex);
>>         throw ex;
>>     }
>>
>>There would be no such prolem to spot whether the exception is included 
>>in the
>>next invocation:
>>
>>         getLogger().debug(ex, "I'm not sure whether to include the
>>exception stack at the end of this message");
>>
>>In conclusion, since this is a new API, it is now the time for such a change
>>(even though in RC6).
>>Please consider the form i suggest, regardless of whether a transition
>>to java 1.5
>>is 1, 2 or 6 years, or months, later.

I generally agree that the current API is not 100% consistent. However, 
that is partially due to the fact that logging systems view exceptions as a 
special parameter meriting special treatment.

In a relatively futuristic scenario where your custom event handling rules 
required you to combine the exception and the parameters in a single event, 
you could write:

logger.error(MyMarkers.EXCETION_AS_PARAM,
             "While fiddling with nose using {} got an exception {}",
             myIndex,
             etiquetteExcetion);

A logging system with marker support could take notice of the 
EXCETION_AS_PARAM marker to print the stack trace for "etiquetteExcetion".

This might sound off base until logging systems start supporting markers, 
e.g. LOGBack.

 > ankostis


Ceki Gülcü




More information about the slf4j-user mailing list