
Joern, Accepting parameters of type Object instead of String opens the door for nasty bugs as you point out. At the same time, it also constitutes an important extension point for logback within the limits imposed by the SLF4J API. I think that the org.slf4j.Logger class should contain a waring (in red) about the arguments being evaluated asynchronously. At present time, we serialize stringified version of the arguments. However, we could imagine that certain types, such as maps and collections, or other well-defined types be serialized as is (without transformation into String). Thus, not only would be it possible to take advantage of specific object types locally but also remotely. Regarding the lazy evaluation of LoggingEvent fields such as caller data and others, the current approach is highly dynamic. For example, if an appender named A requires caller data but is not on the processing path of the current logging event, then caller data will not be evaluated. Setting caller data evaluation as an option at the level of the logger context is not as flexible. Moreover, if any single appender performs the computation of a given field in logging event, that field become available for all subsequent appenders. I tend to think that the way logging event does lazy evaluation of fields works quite well. For the contributor license agreement, please see: http://logback.qos.ch/license.html and http://logback.qos.ch/cla.txt Cheers, Joern Huxhorn wrote:
I can absolutely see Ralphs point but I'd consider it downright dangerous to defer the evaluation to Strings, especially in case of asynchronous appenders.
Take, for example, an object that is persisted using Hibernate. Calling toString() at the wrong time could very well lead to a LazyInitException.
Or worse, what if an Object changes state (and string representation) between the logging call and the evaluation of the message? The message would essentially contain a lie. It would seem that the call to the logging method was different than it was in reality.
Imagining to debug a problem like this is pure horror and would mean "forget logging, use a debugger" all over again :(
And, last but not least, transforming to String[] immediately would also mean that any synchronization/locks would still be the way they (most likely;)) should be.
Concerning your use case, Ralph, aren't you using an XLogger instance for that kind of magic? Couldn't you implement the "magic" part in the XLogger.
As for your suggestion to make LoggingEvent a dumb object with only getters and setters, since several LoggingEvent fields are computed lazily, the computation logic would need to be moved somewhere else, possibly into appenders, which seems like a bad idea to me.
This logic would reside in the Logger, actually. It would, in my scenario, transform the Object[] to String[], resolve the ThreadName and extract CallerData while synchronously creating the actual LoggingEvent.
ThreadName and CallerData evaluation would be activated/deactivated globally instead of in an actual appender. That way, there would be no performance impact if they are not requested.
Evaluating the above mentioned stuff lazily would produce wrong or inaccurate results if executed from a different thread, am I right?
On the host where LoggingEvent data is generated, we just can't ignore lazy computation of certain LoggingEvent fields. Did I misinterpret your idea?
Only the lazy bit. I'd eagerly (synchronously) evaluate everything that is required in Logger but stuff like the creation of the formatted message is done lazily.
I'd have absolutely no problem donating all that code back to both Logback and > SLF4J, although some work would be required to backport it to jdk < 1.5...
I appreciate the offer. You should perhaps consider filing a contributor license agreement. That wouldn't be a problem, I guess, if I'm not required to sell my soul or something ;) Where can I find it? Just let me know when you think it's necessary.
Joern.
-- Ceki Gülcü Logback: The reliable, generic, fast and flexible logging framework for Java. http://logback.qos.ch