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
>>> <[email protected]> wrote:
>>>
>>>
>>> On Mon, Sep 19, 2011 at 10:07 AM, John Vasileff <[email protected]>
>>> 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: [email protected]
For additional commands, e-mail: [email protected]