Serilog Seq Sink не всегда захватывает события

Я запускаю Seq на экземпляре Azure (Windows Server 2012 R2 Datacenter) и регистрируюсь с Serilog из консольного приложения, работающего на моей локальной рабочей станции. У меня настроено 3 приемника - File, Console и Seq. Я также работаю на dnxcore50 (на тот случай, если вы подумали, что мои настройки были недостаточно хитрыми). Все мои события отображаются в консоли и в файле 100% времени. Seq захватывает только события из 1 в 5 или более запусков, то есть он захватывает все события для запусков или ни одного из них. Я использую бесплатную однопользовательскую лицензию для оценки Seq, и я не нашел ничего, что указывало бы на какие-либо ограничения, которые могли бы вызвать такое поведение.

Я настроил SelfLog.Out на регистраторах, но это вообще ничего не регистрирует, кроме моей тестовой строки, которую я добавил, чтобы убедиться, что автоматическая регистрация может, по крайней мере, записать в указанный файл.

public abstract class SerilogBaseLogger<T> : SerilogTarget
{
    protected SerilogBaseLogger(SerilogOptions options, string loggerType)
    {
        LoggerConfiguration = new LoggerConfiguration();
        Options = options;
        LevelSwitch.MinimumLevel = options.LogLevel.ToSerilogLevel();

        var file = File.CreateText(Path.Combine(options.LogFilePath, string.Format("SelfLog - {0}.txt", loggerType)));
        file.AutoFlush = true;
        SelfLog.Out = file;
        SelfLog.WriteLine("Testing self log.");
    }

    // ... snip ....
}

public class SerilogSeqTarget<T> : SerilogBaseLogger<T>
{
    public string Server => Options.Seq.Server;

    public SerilogSeqTarget(SerilogOptions options)
        : base(options, string.Format("SerilogSeqTarget[{0}]", typeof(T)))
    {
        LoggerConfiguration
            .WriteTo
            .Seq(Server);

        InitializeLogger();
    }

    public override string ToString()
    {
        return string.Format("SerilogSeqTarget<{0}>", typeof(T).Name);
    }
}

public class SerilogLoggerFactory<TType> : LoggerFactory<SerilogTarget>
{
    // .... snip ....

    public override IMyLoggerInterface GetLogger()
    {
        var myLogger = new SerilogDefaultLogger()
            .AddTarget(SerilogTargetFactory<TType>.GetFileTarget(Options))
            .AddTarget(SerilogTargetFactory<TType>.GetConsoleTarget(Options))
            .AddTarget(SerilogTargetFactory<TType>.GetSeqTarget(Options));

        myLogger.Info("Logger initialized with {@options} and targets: {targets}", Options, ((SerilogDefaultLogger)myLogger).Targets);

        return myLogger;
    }
}

public class SerilogTargetFactory<TType>
{
    // ... snip ...

    public static SerilogTarget GetSeqTarget(SerilogOptions options)
    {
        return !string.IsNullOrEmpty(options.Seq.Server)
                   ? new SerilogSeqTarget<TType>(options)
                   : null;
    }
}

Какие-либо предложения? Является ли это просто побочным эффектом того, что вы находитесь на переднем крае, работаете с предварительным выпуском всего (хотя в этом случае я ожидаю, что что-то пойдет несколько последовательно)?

1 ответ

Решение

При нацеливании dnxcore50/CoreCLR, Serilog не может подключиться AppDomain завершение работы, чтобы гарантировать, что все буферизованные сообщения всегда сбрасываются. (AppDomain не существует в этом профиле:-)

Есть несколько вариантов:

  1. Утилизируйте регистраторы (особенно Seq) при завершении работы:

    (логгер как IDisposable)?.Dispose();

  2. Используйте статический Log класс и назовите его CloseAndFlush() метод на отключение:

    Log.CloseAndFlush ();

Последнее - использование статического Log класс вместо различного человека ILogger экземпляры - это, пожалуй, самый быстрый и простой способ начать работу, но он имеет тот же эффект, что и утилизация регистраторов, поэтому любой подход должен это сделать.

Другие вопросы по тегам