Serilog - вход в многопоточную систему отмены приложения - PullRequest
1 голос
/ 26 сентября 2019

У меня проблемы с корректным завершением работы приложения .NET Core, которое регистрируется в приемнике Serilog ElasticSearch из нескольких потоков.Ниже приведен минимальный рабочий пример:

Program.cs:

using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Serilog;

public class Program
{
    public static async Task Main() =>
        await new HostBuilder()
            .UseConsoleLifetime()
            .ConfigureLogging((context, logging) => logging.AddSerilog(
                new LoggerConfiguration()
                    .WriteTo.Console()
                    .WriteTo.Elasticsearch(
                        nodeUris: "http://example.com:9200",
                        indexFormat: "derp-{0:yyyy.MM.dd}",
                        typeName: "_doc"
                    )
                .CreateLogger(), dispose: true)
            )
            .ConfigureServices((context, services) =>
            {
                services.AddHostedService<DerpService>();
            })
        .Build()
        .RunAsync();
}

DerpService.cs:

using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;

public class DerpService : BackgroundService
{
    private readonly ILogger<DerpService> _logger;
    public DerpService(ILogger<DerpService> logger)
    {
        _logger = logger;
    }
    protected override async Task ExecuteAsync(CancellationToken stoppingToken) =>
        await Task.WhenAll(Enumerable
            .Range(0, 100)
            .Select(i =>
                Task.Run(() =>
                {
                    while (!stoppingToken.IsCancellationRequested)
                    {
                        _logger.LogInformation($"Task {i} is here!");
                    }
                }, stoppingToken)
        ));
}

Когда я запускаю это приложение, Serilog немедленно начинает писатьцелая куча Task i is here! сообщений для консоли, но ничего не регистрируется в ElasticSearch в течение нескольких минут.После запуска журналов ElasticSearch они все больше отстают по мере продолжения работы приложения.Кроме того, потребление памяти приложения увеличивается, по-видимому, без ограничений, с экземплярами Serilog.Events.LogEvent.Наконец, когда я пытаюсь отменить приложение с помощью Ctrl+C в окне консоли, журналы консоли останавливаются, а потребление памяти снижается, но приложение остается живым еще несколько минут, предположительно, пока Serilog обрабатывает отставание LogEvent s для отправки в ElasticSearch.

Ясно, что я забиваю приемник Serilog ElasticSearch большим количеством одновременных журналов, чем это когда-либо предполагалось обрабатывать, но это кажется раздражающими проблемами для any многопоточное приложение с логированием.В частности:

  1. Имеет ли ElasticSearch максимальную скорость ведения журнала, которую он может обрабатывать?Есть ли хорошие способы сделать это быстрее?
  2. Я думал, что общие хосты .NET Core должны были автоматически отключаться через 5 секунд .Как быть с тем, что приемник ElasticSearch не позволяет хосту завершить работу приложения?
  3. Есть ли способ принудительно отменить Serilog после того, как Ctrl+C выдает команду на завершение работы приложения (при условии, что мне нет дела до оставшегося журналасобытия)?

Заранее спасибо!

...