I think it's much easier to discuss something concrete, so I've put up an 
incomplete version of the AsyncAppenderSkeleton I envisage on the following 
branch:

https://github.com/JJoe2/log4net/tree/wip/AsyncAppender

I would appreciate it if you could review this and let me know if you're happy 
to go in this direction before I invest more time in it.

Some notes on this implementation:

1. I've created a new class AppenderBase into which I've extracted all the code 
from AppenderSkeleton that I want to reuse in AsyncAppenderSkeleton.  
AppenderSkeleton derives from this class.  The purpose here is twofold (a) to 
avoid duplication of code between AppenderSkeleton and AsyncAppenderSkeleton 
and (b) to make it easier to review the AsyncAppenderSkeleton class.

2. The queue implementation is a separate class that implements IAppenderQueue 
which I haven't implemented yet.  I plan to write three classes (a) a base 
AppenderQueueSkeleton class with common stuff to be shared by all queues 
(default error / retry handling etc); (b) a class that uses a simple lossy 
in-memory FIFO queue (System.Collections.Queue); (c) a class that uses MSMQ so 
the queue can be made persistent.

3. The class operates in synchronous mode by default, and is intended to be 
functionally identical to AppenderSkeleton.

4. When in asynchronous mode, by default LoggingEvents are queued after being 
fixed, and the Append method of the derived class is called as logging events 
are dequeued.

5. Alternatively, a derived class can override FormatLoggingEvent to format the 
logging event before it is queued.  In this case, a new method 
AppendFormattedEvents of the derived class is called instead of Append as 
events are dequeued.  This can improve performance, because it avoids the need 
to fix properties of LoggingEvent.

6. The IOptionHandler.ActivateOptions implementation has error handling.  If 
the appender is not configured successfully, it will ignore any logging events 
it receives.

7. I haven't done any work on the locking yet, but the intention is to hold a 
lock while Append is called, so that the derived class can rely on the fact 
that Apppend will never be called concurrently by multiple threads.




Reply via email to