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