Как создать асинхронную оболочку для log4net? - PullRequest
30 голосов
/ 12 августа 2011

По умолчанию log4net - это механизм синхронного ведения журнала, и мне было интересно, есть ли способ вести асинхронное ведение журнала с помощью log4net?

Ответы [ 6 ]

13 голосов
/ 16 февраля 2012

Просто хотел предоставить мое полное решение для справки.Пара важных элементов FixFlags позволяет вам захватить поток, который фактически выполняет регистрацию.Коллекция блокировок находится в ReactiveExtensions.Суть здесь в том, что ваш перенаправляющий обработчик обрабатывает асинхронные операции, а затем просто пересылает LoggingEvent стандартному приложению Log4Net, что позволяет Log4Net делать все то, что у него хорошо получается.Не нужно заново изобретать колесо.

/// <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);
            }
        }
    }
}

Затем в файле log4net.xml вы настраиваете таким образом добавляющие

<!-- 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>

Обновление:

Если вы хотите использовать контекст в log4net как "log4net.ThreadContext.Properties["CustomColumn"]"

Тогда вам нужно обновить приведенный выше код, например

loggingEvent.Fix = FixFlags.All;
13 голосов
/ 12 августа 2011

Если вы зайдете на сайт log4net, вы можете найти несколько примеров, по крайней мере один из которых - асинхронный Appender.

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

Обратите внимание, что я не использовал ни один из этих примеров, поэтому я не могу поручиться за них так или иначе.

Вот ссылка на фактического асинхронного приложения из области примеров log4net в их хранилище кода:

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

Я кратко посмотрел на него, и он, очевидно, действует как обертка вокруг одного или нескольких «обычных» Аппендеров. При каждом запросе журнала (содержащем один или несколько объектов LoggingEvent) поток ThreadPool используется для пересылки событий LoggingEvents в список завернутых приложений.

11 голосов
/ 12 августа 2011

Вот как я это делаю:

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

Таким образом log4net выполняет ведение журнала в отдельном потоке, асинхронно ...

Кстати, Task класс находится в System.Threading.TasksПространство имен.

7 голосов
/ 02 января 2016

Некоторые из представленных здесь идей неверны и приводят к неверным / устаревшим данным, неправильной регистрации или очень плохой производительности.Например, в принятом ответе предлагается использовать log4net AsyncAppender, в котором используется ThreadPool, что приводит к ошибкам записи, что может быть проблемой для некоторых, но я, конечно, хочу, чтобы мои события в журнале были один за другим, что также может иметь ужасную производительностьи слишком много напрягает ThreadPool, также он не группирует записи журнала.Ответ, предложенный Джонатаном, безусловно, является гораздо лучшим решением, но ему все еще не хватает оптимальной производительности.

Хороший пример того, как это должно быть реализовано, можно найти ЗДЕСЬ , а также результаты сравнительного анализа и пояснения ЗДЕСЬ .

Еще одна хорошая особенность этого решения заключается в том, что оно было реализовано в виде Forwarder, а не Appender, позволяя пользователю включать более одного Appender и регистрироваться в каждом из них.из них одновременно.

5 голосов
/ 15 февраля 2012

Я столкнулся с этой проблемой на этой неделе, однако я не хотел продолжать отправлять запросы в пул потоков, потому что это могло в конечном итоге привести к истощению остальной части приложения потоков, поэтому я пришел к Asyncronous appender, который запускает выделенный поток для добавления, которое подается через буфер. Проверьте это здесь: https://github.com/cjbhaines/Log4Net.Async

0 голосов
/ 27 февраля 2019

https://github.com/cjbhaines/Log4Net.Async

Теперь у нас есть асинхронные методы log4net.Для людей, которые ищут обновленные ответы.

https://www.nuget.org/packages/Log4Net.Async/

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...