NLog AsyncTaskTarget не выполняет пакетную обработку строк после первой итерации

#c# #nlog

#c# #nlog

Вопрос:

Я пытаюсь написать пользовательскую цель async для NLog, которая отправляет журналы в Azure, и столкнулся с неожиданным сценарием. В основном это: когда асинхронная задача, которую я вызываю, выполняется медленно (в этом примере 1,5 с), после первого пакета все оставшиеся записи журнала отправляются отдельными пакетами.

Это воспроизводимо с различными значениями для TaskDelayMilliseconds и различными задержками приложения. Я бы ожидал одну операцию «Записи» каждые «TaskDelayMilliseconds», за исключением случаев исключений / повторных попыток. Я подозреваю, что это может быть ошибкой в AsyncTaskTarget, но я хотел бы получить отзыв сообщества, прежде чем отправлять его. Есть мысли? Заранее спасибо.

Для этого кода требуется NLog Nuget 4.6.0-rc3. Новые асинхронные пакетные методы для переопределения недоступны в текущей версии.

 [Target("AsyncTestTarget")]
public class AsyncTestTarget : AsyncTaskTarget
{
    protected override void InitializeTarget()
    {
        base.InitializeTarget();

        BatchSize = 10000;
        TaskDelayMilliseconds = 3000;
    }


    protected override Task WriteAsyncTask(LogEventInfo logEvent, CancellationToken cancellationToken)
    {
        InternalLogger.Info($"NLog.Extensions.AsyncTestTarget.WriteAsyncTask()");
        return WriteAsyncTask(new List<LogEventInfo> {logEvent}, cancellationToken);
    }

    protected override Task WriteAsyncTask(IList<LogEventInfo> logEvents, CancellationToken cancellationToken)
    {
        InternalLogger.Info($"NLog.Extensions.AsyncTestTarget.WriteAsyncTask(List) : {logEvents.Count}");
        if (!logEvents.Any())
            return Task.CompletedTask;
        // If this line is commented, the rows are batched as expected.  If this line is left as-is, then after the first batch, records are sent one at a time.
        System.Threading.Thread.Sleep(TimeSpan.FromMilliseconds(1500));

        return Task.CompletedTask;
    }
}
  

Пример программного кода:

 class Program
{
    static ILogger logger = LogManager.GetCurrentClassLogger();
    static void Main(string[] args)
    {

        for (var i = 0; i < 5000; i  )
        {
            logger.Info(i.ToString());
            System.Threading.Thread.Sleep(TimeSpan.FromMilliseconds(100));
        }

        logger.Info("Done");

        LogManager.Flush(TimeSpan.FromSeconds(15));
    }
}
  

Конфигурация NLog:

 <nlog internalLogLevel="Debug" internalLogToConsole="true">
    <extensions>
      <add assembly="ConsoleApp1"/>
    </extensions>

    <targets>
      <target type="console" name="console"/>
      <target type="AsyncTestTarget" name="test" />
    </targets>

    <rules>
      <logger name="*" minlevel="Trace" writeTo="console" />
      <logger name="*" minlevel="Trace" writeTo="test" />
    </rules>
</nlog>
  

Скриншот без ожидания в WriteAsyncTask:
Снимок экрана # 1

Скриншот со спящим режимом в WriteAsyncTask (ошибка): Снимок экрана # 2

Комментарии:

1. Если вы считаете, что это ошибка, пожалуйста, опубликуйте ее здесь: github.com/NLog/NLog/issues/new/choose

2. Смотрите также github.com/NLog/NLog/issues/3185

Ответ №1:

Выпущен NLog 4.6.1, который разрешает # 3185 : https://www.nuget.org/packages/NLog