2

I'm running Seq on an Azure instance (Windows Server 2012 R2 Datacenter) and logging with Serilog from a console application running on my local workstation. I have 3 sinks configured - File, Console and Seq. I'm also running on dnxcore50 (just in case you were thinking my setup wasn't dodgy enough). All my events are showing up in console and the file 100% of the time. Seq is only capturing event about 1 in 5 or more runs, that is it will either capture all the events for the run or none of them. I am using the free single user license to evaluate Seq, and I haven't found anything to suggest there are any limitations that would cause this behavior.

I've set up SelfLog.Out on the loggers, but that logs nothing at all, other than my test line which I added to make sure the self logging could at least write to the specified file.

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

Any suggestions? Is this just a side-effect of being on the bleeding edge, working with pre-release everything (although in that case I'd expect things to fail somewhat consistently)?

Nicholas Blumhardt
  • 30,271
  • 4
  • 90
  • 101
Colin Young
  • 3,018
  • 1
  • 22
  • 46

1 Answers1

3

when targeting dnxcore50/CoreCLR, Serilog can't hook into AppDomain shutdown to guarantee that any buffered messages are always flushed. (AppDomain doesn't exist in that profile :-)

There are a couple of options:

  1. Dispose the loggers (especially the Seq one) on shutdown:

    (logger as IDisposable)?.Dispose();

  2. Use the static Log class and call its CloseAndFlush() method on shutdown:

    Log.CloseAndFlush();

The latter - using the static Log class instead of the various individual ILogger instances - is probably the quickest and easiest to get going with, but it has exactly the same effect as disposing the loggers so either approach should do it.

Nicholas Blumhardt
  • 30,271
  • 4
  • 90
  • 101
  • That did the trick. I made my `SerilogBaseLogger` implement `IDisposable` and also for my targets (those would be Sinks in Serilog parlance), and that seems to have made things more reliable. Probably a good idea anyway (I'm playing with/converting an old log framework/wrapper and there's a good chance it isn't cleaning up properly after itself anyway). – Colin Young Dec 10 '15 at 16:00
  • Great, glad to hear it's sorted out. Cheers! – Nicholas Blumhardt Dec 10 '15 at 21:33
  • So, it turns out that I'm still seeing the issue, but with setting the buffer file name, it at least gets there eventually. At this point I'm inclined to blame either me IDisposable pattern or the RC stat of dnxcore50. I'll revisit and update once the final release is out, but in case anyone else comes across this in the meantime... – Colin Young Dec 23 '15 at 19:41
  • I was using the `Serilog.Sinks.MSSqlServer` and had the same issue. File and Console logs existed, but DB ones were not written at all. Using a route that calls `Log.CloseAndFlush()` ended up writing all 500+ lines of logs out to the DB in one instance. – Nick Feb 04 '19 at 18:31