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.go...@dslextreme.com> wrote:
>>> 
>>> 
>>> On Mon, Sep 19, 2011 at 10:07 AM, John Vasileff <john.li...@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-unsubscr...@logging.apache.org
For additional commands, e-mail: log4j-dev-h...@logging.apache.org

Reply via email to