Я пытаюсь написать пользовательскую асинхронную цель для 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:
Скриншот со сном в WriteAsyncTask (ошибка):