[slf4j-dev] Benefits of Message objects?

jvasileff john.lists at gmail.com
Thu Sep 8 01:00:33 CEST 2011


Joern Huxhorn wrote:
> 
> Ok, huge post is incoming... ;)
> 

Huge post right back at you!

I like the idea of using Message objects.  Let me start by sharing ideas I
have based on my proposal in bug 31, but then I'll come back and try to
show that these are complimentary approaches.

Goals:

1) Compatibility with legacy loggers

2) Provide supplementary logging information (Map<String, Object> or
StructuredData) that appenders can add in some way to the log entry similar
to NDC/MDC.

3) Support custom log formatters, such as java.util.formatting

4) A custom log formatter that can use #2 (your example of "{Foo} {Bar}
{Foobar}")

5) Lazy & memoized formatting for performance.

SUPPLEMENTAL DATA

A key part of this is #2, providing "supplementary data" to a log method.
For this, we could add the following methods to the Logger interface:

public void trace(Map supplementalData);
public void trace(Map supplementalData, String msg);
public void trace(Map supplementalData, String format, Object... args);

public void trace(Marker marker, Map supplementalData);
public void trace(Marker marker, Map supplementalData, String msg);
public void trace(Marker marker, Map supplementalData, String format,
      Object... args);

and the same for other levels.

The supplementalData argument may in fact be a StructuredData implements
Map object.  Message formatters and appenders can optionally use instanceof
to treat StructuredData objects uniquely.  This is for bug 148.

Bug 31 AbstractLogger's abstract log method could take Map supplementalData
as an argument, but see below.

FORMATTING

The idea in http://bugzilla.slf4j.org/show_bug.cgi?id=31#c94 provides
custom formatting:

Logger myLogger = LoggerFactory.getLogger(MyClass.class)
        .formatWith(SLF4JFormatters.JAVA_UTIL_FORMATTER);

A new formatter that perfoms substitutions ("{foo}") could be specified
this way.  Ideally this new formatter would support supplementalData as
well as NDC and MDC.

COMPATIBILITY #1

Bug 31's style of adding methods to NamedLoggerBase would make it possible
to add these features to most pre-existing loggers.  Custom formatting
would of course require delegating to the trace(String msg, Exception t)
style
methods which would hide the arg[] from the adapter.  Aside from custom
formatting, pre-existing loggers would ignore supplemental data.

So far, we have #1, #2, #3, and #4, building on the current Logger
interface, and providing decent compatibility.

MESSAGE OBJECTS

Now, to add Message Objects to the application facing API, we could add the
following additional methods to the Logger interface (slight change to your
proposal, but sticking with current trace/debug/etc. style methods):

public void trace(Message message);
public void trace(Marker marker, Message message);

interface Message {
    String getFormattedMessage();
    String getMessagePattern();
    Object[] getParameters();
    Throwable getThrowable();
    Map getSupplementalData();
}

This Message interface is similar your ParameterizedMessage class.  Having
more than just getFormattedMessage() in the base interface helps provide
the adapter all interesting parts of the message.

The Logging.formatWith(formatter) option described above would be ignored
for logs made with a message parameter.  The Message object would be
responsible for formatting.

The next step is to leverage Message objects in the AbstractLogger
interface.  Building on bug 31, we now have:

protected abstract void log(Marker marker, Level level, Message message);

which is very close to what you have, but includes the Throwable as part
of the Message.

AbstractLogger would wrap arguments to the non-Message Logger methods with
a default Message implementation, and include the "formatWith" formatter.
Actual adapter implementations would deal only with Message objects,
regardless how the call was made.

So, this finally gives us #4 - lazy formatting.

COMPATIBILITY #2

Similar to COMPATIBILITY #1, we can enhance NamedLoggerBase to support
Message objects.  Old adapters will be supported.

To head off future compatibility issues, all Message implementations should
extend an AbstractMessage class.  AbstractMessage will basically return
nulls (or better, EMPTY_MAP, etc..) for each method.

APPLICATION USAGE

I think most application code will use the non-Message methods.  Having to
instantiate a message is a burden unless you really need it.  Specifying a
custom formatter is easier done one time when creating the logger.  If
adding supplemental data is required, it may already be available in the
form of a Map, or if not, it may be easier to create a Map than a Message
object.

That being said, I think the ability to override the formatter once or
twice in a class, handle specific requirements like the Hibernate issue you
raised, or whatever else, makes a very compelling case to support Message
objects in the application facing API.

John

--
View this message in context: http://slf4j.42922.n3.nabble.com/Benefits-of-Message-objects-tp3316674p3318183.html
Sent from the slf4j - dev mailing list archive at Nabble.com.


More information about the slf4j-dev mailing list