logging-log4j-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From John Vasileff <john.li...@gmail.com>
Subject Re: log4j2 parameterized msg with throwable
Date Tue, 20 Sep 2011 01:39:01 GMT

On Sep 19, 2011, at 8:51 PM, Ralph Goers wrote:

> 
> On Sep 19, 2011, at 3:19 PM, Joern Huxhorn wrote:
> 
>> 
>> On 19.09.2011, at 22:09, ralph.goers @dslextreme.com wrote:
>> 
>>> 
>>> 
>>> On Mon, Sep 19, 2011 at 1:07 PM, ralph.goers @dslextreme.com <ralph.goers@dslextreme.com>
wrote:
>>> 
>>> 
>>> On Mon, Sep 19, 2011 at 10:07 AM, John Vasileff <john.lists@gmail.com>
wrote:
>>> 
>>> What do you think about an optional LazyRenderMessage interface (I'm sure there
is a better name for this) that could be used by Message types that have expensive constructers?
>>> 
>>> interface LazyRenderMessage {
>>> void render();
>>> }
>>> 
>>> The logger would call render() immediately after checking isEnabled for level
and marker.  So, this should not affect serialization - the object will either be fully constructed
or discarded right away.
>>> 
>>> This would allow ThreadDumpMessage Thread.getAllStackTraces() work to be avoided
unless logging will actually occur (or is likely to occur in the case of complex filters).
>>> 
>>> The benefit of course is that trace(THREAD_DUMP_MARKER, new ThreadDumpMessage())
could be left in production code without if isTraceEnabled(...) { ... }, and with very little
overhead - creating a short lived object that does nothing in the constructor is pretty cheap
these days.
>>> 
>>> This would also help for Message types like ParameterizedMessage to avoid parseArguments(arguments)
when they are created by application code.
>>> 
>>> I see some merit in this idea. But you are right, it really needs a better name.
>>> 
>>> One other point, though, is that there should always be a constructor that allows
immediate rendering. I could easily see the ThreadDumpMessage being used for other purposes
and never being passed to a logger. For example, I could create two ThreadDumpMessages at
slightly different points in time and then only print the differences between them.
>>> 
>> 
>> But the whole idea of the Message interface was the lazy evaluation of the expensive
String creation with the suggestion to also cache those strings for reuse. Otherwise using
toString() wouldn't make a big difference...
>> 
>> Printing the differences between two ThreadDumpMessages would be an additional functionality,
of course. I guess that something like a populate() method filling in the stacktrace (separate
from string creation) would make sense. That could be called automatically if it wasn't called
explicitly before execution of getFormattedMessage()...
> 
> A ThreadDumpMessage pretty much has to capture all the data immediately or its usefulness
would be quite limited. If you look at the way I implemented that class you will see it captures
the thread information in the constructor. However, it doesn't actually build the formatted
String until the first call to getFormattedMessage.  This is actually what you would want
if one were to create a ThreadDumpDiffMessage. 
> 
> John's proposal is to have the ThreadDumpMessage constructor do nothing. The Thread data
wouldn't be captured until the render method is called. You've basically said the same thing
with regard to the populate method. Although my preference would be to have constructors that
allow for both I guess I'd also be OK with having the populate/render/initialize method return
the Message so that you could do 
> 
> ThreadDumpMessage msg = new ThreadDumpMessage.populate();
> 
> If Logger is going to call the populate method then it obviously has to check whether
that has already been done.
> 
> Ralph
> 
> 

package org.apache.logging.log4j.message;

/**
 * A Message that supports lazy initialization.
 */
public interface InitializingMessage extends Message {

  /**
   * Lazily perform expensive initialization tasks that would otherwise occur in
   * the constructor. For example, cloning mutable message content or gathering
   * data to be logged. Loggers are required to call this method immediately
   * after determining this Message is likely to be logged based on the log
   * Level and Marker, and before returning from the log method (i.e.
   * trace(message)). The Logger will not call initialize() if no logging will be
   * performed based on Level and Marker.
   * 
   * Initialization must be performed before returning from the first call to this
   * method. Subsequent calls must be no-ops.
   * 
   * @return This Message.
   */
  Message initialize();

}

John
---------------------------------------------------------------------
To unsubscribe, e-mail: log4j-dev-unsubscribe@logging.apache.org
For additional commands, e-mail: log4j-dev-help@logging.apache.org


Mime
View raw message