I haven't worked any more on this, but I do intend to do so. I thought that I would at least give a heads up that this issue isn't dead.
The current approach has a couple of drawbacks:
it incurs a synchronization for every dispatched message,
yes
it adds a sequenceCount to the LoggingEvent which breaks serialization compatibility with 1.2.x
true, but once 1.3 is released, probably no one will care.
and might be mis-interpreted as a reliable means to detect dropped messages,
This is a lopsided argument, lying beyond the realm of the rational, which I find quite disturbing. It has been brought to the table before. I have given 3 solid reasons why no rational being could ever use it for missing message detection. If required, we can go over them again. See also http://marc.theaimsgroup.com/?l=log4j-dev&m=110442953800184&w=2
and would report as equal serializations of the same object in different states (discussed later).
true, but exactly the same can be said about the implementation which inspects each LoggingEvent field one by one. Presumably, even that implementation will first compare events for address equality. In the current log4j processing chain the same LoggingEvent instance can be modified as it is handled by different appenders.
Since LoggingEvents have a short lifetime, the values of Object.hashCode (which I believe are similar to memory addresses) may repeat and likely in an implementation dependent fashion.
I don't understand what you are trying to say. In any case, the current LoggingEvent.hashCode implementation is damn near ideal.
The approach that seems most reliable to me is to implement LoggingEvent.equals as a real value comparison and create a corresponding LoggingEvent.hashCode. That would avoid synchronization tax on every logging request and would only cost the callers of LoggingEvent.equals and LoggingEvent.hashCode.
Point well taken. The tradeoff between the creation cost for everyone and the cost for the callers of LoggingEvent.equals and LoggingEvent.hashCode should be considered with care.
The implementation would need to be start enough so that a cloned through serialization object would compare equal to the original and that prepareForDeferredProcessing would not effect either equals or hashCode.
There would be at least two cases where the approaches give observably results. If distinct logging event with content and timestamp were received the current approach would report the messages as distinct while the new approach would report the messages as equal. This would only occur in tight loops like:
for (int i = 0; i < 20; i++) { logger.info("Hello, world"); }
The current approach would see that as twenty distinct messages while the new approach would see all messages within the same millisecond as identical.
Hence the necessity for a sequence counter.
The other scenario is that the current approach sees all deserialized copies of the same original object instance as identical.
Yes, that is the intended behavior.
log4j 1.3 adds setter methods to LoggingEvent that are used by Filters to change the message and other aspects of the logging event. If a message is sent using the SocketAppender both before and after Filter processing, with the current approach the messages would be seen as identical even though the message content, level and other aspects could be radically different.
As mentioned above, that's the risk we take by allowing post-processing by filters.
My attack plan would be to first add unit tests that should check the essential features on any acceptable approach and should be passed by the current implementation, all the equals contract test cases (equals to self, equals to null), comparison to deserialized clone, hashCode invariant after prepareForDeferredProcessing. Then I would try to flesh out the implementation and corresponding tests for the value comparison implementation and report back to the list before proceeding.
Test cases. Mmmmmm.
-- Ceki Gülcü
The complete log4j manual: http://www.qos.ch/log4j/
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]