¿Cómo puedo crear un wrapper asincrónico para log4net?


Por defecto, log4net es un mecanismo de registro síncrono, y me preguntaba si había una manera de tener un registro asíncrono con log4net?

 27
Author: pcdev, 2011-08-12

5 answers

Si va al 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 utilizado ninguno de estos ejemplos, por lo que no puedo responder por ellos de una manera u otra.

Aquí hay un enlace al appender asincrónico real desde el área de ejemplos de log4net en su código repositorio:

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 Anexores "convencionales". En cada solicitud de registro (que contiene uno o más objetos LoggingEvent), se utiliza un subproceso ThreadPool para reenviar los LoggingEvents a la lista de anexores empaquetados.

 13
Author: wageoghe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-08-12 18:36:10

Solo quería proporcionar mi solución completa para referencia. Un par de elementos importantes, los FixFlags le permiten capturar el hilo que realmente está haciendo el registro. La Colección de Bloqueo está en ReactiveExtensions. La clave aquí es que su appender de reenvío maneja las cosas asíncronas y luego simplemente reenvía en el LoggingEvent a un appender Log4Net estándar, que permite a Log4Net hacer 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);
            }
        }
    }
}

Entonces, 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 utilizar el contexto en log4net como "log4net.ThreadContext.Properties["CustomColumn"]"

Entonces necesitas actualizar el código anterior como

loggingEvent.Fix = FixFlags.All;
 13
Author: Jonathan Beerhalter,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-06-10 10:20:09

Así es como lo hago:

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

De esa manera log4net realiza el registro en un subproceso separado, de forma asíncrona...

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

 12
Author: Dean Kuga,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-08-12 18:20:40

Algunas de las ideas aquí son incorrectas y dan como resultado datos no válidos/obsoletos, registros fuera de servicio o muy mal rendimiento. Por ejemplo, la respuesta aceptada sugiere usar el log4net AsyncAppender que usa el ThreadPool resultando en entradas fuera de orden que podrían no ser un problema para algunos, pero ciertamente quiero que mis eventos de registro sean uno tras otro también puede tener un rendimiento terrible y poner demasiada presión en el ThreadPool también no lote las entradas de registro. La respuesta sugerida por Jonathan es sin duda una solución mucho mejor, pero todavía carece de un rendimiento óptimo.

Un buen ejemplo de cómo se debe implementar esto se puede encontrar AQUÍ y los resultados de la evaluación comparativa y la explicación AQUÍ.

Otra buena característica de esta solución es que se ha implementado como un Forwarder no Appender que permite al usuario incluir más de una Appender y registro de cada uno de ellos al mismo tiempo.

 6
Author: MaYaN,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-02-09 08:38:26

Me encontré con este problema esta semana, sin embargo, no quería seguir disparando solicitudes al grupo de subprocesos porque podría terminar muriendo de hambre el resto de la aplicación de subprocesos, así que se me ocurrió un anexador asincrónico que ejecuta un subproceso dedicado para anexar que se alimenta a través de un búfer. Échale un vistazo aquí: https://github.com/cjbhaines/Log4Net.Async

 4
Author: Chris Haines,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-26 22:15:44