¿Cómo creo un contenedor asíncrono para log4net?

¿Cómo creo un contenedor asíncrono para log4net?

Solo quería proporcionar mi solución completa como referencia. Un par de elementos importantes, FixFlags le permiten capturar el hilo que realmente está realizando el registro. La colección de bloqueo está en ReactiveExtensions. La esencia aquí es que su agregador de reenvío maneja las cosas asincrónicas y luego simplemente reenvía en LoggingEvent a un agregador Log4Net estándar, que permite que Log4Net haga todas las cosas en las que es bueno. Nada de reinventar la rueda.

/// <summary>
/// Provides an extension for the log4net libraries to provide ansynchronous logging capabilities to the log4net architecture
/// </summary>
public class AsyncLogFileAppender : log4net.Appender.ForwardingAppender
{
    private static int _asyncLogFileAppenderCount = 0;
    private readonly Thread _loggingThread;
    private readonly BlockingCollection<log4net.Core.LoggingEvent> _logEvents = new BlockingCollection<log4net.Core.LoggingEvent>();

    protected override void Append(log4net.Core.LoggingEvent loggingEvent)
    {
        loggingEvent.Fix = FixFlags.ThreadName;
        _logEvents.Add(loggingEvent);
    }

    public AsyncLogFileAppender()
    {

        _loggingThread = new Thread(LogThreadMethod) { IsBackground = true, Name = "AsyncLogFileAppender-" + Interlocked.Increment(ref _asyncLogFileAppenderCount), };
        _loggingThread.Start();
    }

    private void LogThreadMethod()
    {
        while (true)
        {
            LoggingEvent le = _logEvents.Take();
            foreach (var appender in Appenders)
            {
                appender.DoAppend(le);
            }
        }
    }
}

Luego, en su log4net.xml, configura los appenders de esta manera

<!-- Standard form output target location and form -->
<appender name="StandardAppender" type="TSUIC.Logging.AsyncLogFileAppender">
<appender-ref ref="StandardAppenderSync" />
</appender>

<appender name="StandardAppenderSync" type="log4net.Appender.RollingFileAppender">
    <!-- The standard pattern layout to use -->
    <file value="log\Log_" />
    <appendToFile value="true" />
    <rollingStyle value="Date" />
    <maxSizeRollBackups value="-1" />
    <maximumFileSize value="5GB" />
    <lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
    <staticLogFileName value="false" />
    <datePattern value="yyyyMMdd'.txt'" />
    <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%date [%thread] %-5level %logger - %message%newline" />
    </layout>
</appender>

Actualización:

Si desea usar contexto en log4net como "log4net.ThreadContext.Properties["CustomColumn"] "

Entonces necesita actualizar el código anterior como

loggingEvent.Fix = FixFlags.All;

Si visita el sitio web de log4net, puede encontrar algunos ejemplos, al menos uno de los cuales es un Appender asíncrono.

http://logging.apache.org/log4net/release/example-apps.html

Tenga en cuenta que no he usado ninguno de estos ejemplos, por lo que no puedo responder por ellos de una forma u otra.

Aquí hay un enlace al agregador asíncrono real del área de ejemplos de log4net en su repositorio de código:

http://svn.apache.org/viewvc/logging/log4net/trunk/examples/net/2.0/Appenders/SampleAppendersApp/cs/src/Appender/AsyncAppender.cs?view=markup

Lo miré brevemente y aparentemente actúa como un envoltorio alrededor de uno o más Appenders "convencionales". En cada solicitud de registro (que contiene uno o más objetos LoggingEvent), se utiliza un subproceso ThreadPool para reenviar LoggingEvents a la lista de Appenders envueltos.


Así es como lo hago:

Task.Factory.StartNew(() => log.Info("My Info"));

De esa manera, log4net realiza el inicio de sesión en un subproceso separado, de forma asíncrona...

Por cierto, Task la clase está en System.Threading.Tasks espacio de nombres.