使用Serilog登录到Splunk时丢弃的日志消息

时间:2019-09-05 08:57:38

标签: c# .net core splunk serilog

我们有一个Windows服务,该服务创建一个新线程并每天运行一次计划任务。使用Serilog完成记录,接收器为Splunk(“ Serilog.Sinks.Splunk”)。在成功运行期间,我们将八条信息消息写入日志(Log.Information(“”))。从时间戳记到时间戳记和整数值,消息从一次运行到另一次运行几乎相同。在完成实际作业任务之前记录了四个消息,在完成之后记录了四个消息。

我们发现,有时所有8条消息都在Splunk中出现,有时仅显示最后4条消息(在耗时的处理完成后记录的消息),有时没有一条消息。

当我们添加另一个接收器并将其写入文件(“ Serilog.Sinks.File”)时,我们始终会获得文件中的所有八条消息。

添加Serilog调试日志记录(Serilog.Debugging.SelfLog.Enable),当丢弃日志消息时,我们将记录以下调试消息(一次-每条丢失的消息不记录一条): “尝试发送到https:// <> / services / collector时,收到了禁止的2019-08-30T11状态代码,该事件已被丢弃,不会重新放入队列。” / p>

在计划任务中添加睡眠(System.Threading.Thread.Sleep())的第一件事是,我们总是在Splunk中的Sleep之后完成日志记录,因此似乎需要一些时间来建立与Splunk的连接端点,并且在连接建立之前发送的所有消息都将被丢弃。由于其中三个消息是在执行进入我们的代码之前由外部nuget程序包(Hangfire)记录的,因此我们经常丢失这三个消息,因此在代码中包含Sleep()是不理想的。

伪代码(包括睡眠),如我所描述的,日志消息1-3(和6-8)是由外部nuget包编写的:

    public Task DoJob()
    {
        var currentRunInformation = new RunInformation();
        try
        {
            System.Threading.Thread.Sleep(3000);
            Log.Information($"Log message 4");

            //Get Data
            var jobData = GetJobData();
            //Do some calculations
            var calculated = DoCalculations(jobData);

            //Save result
            PersistResult(calculated);

            Log.Information($"Log message 4");
            return Task.CompletedTask;
        }
        catch (Exception exception)
        {
            Log.Error(exception, $"Error log");
            return Task.FromException(exception);
        }
    }

有什么方法可以使日志记录在发送消息之前等待打开的连接?还是有其他选择可以避免以不可预测的方式丢弃日志?

1 个答案:

答案 0 :(得分:2)

Serilog.Sinks.Splunk中没有开箱即用的功能,可以在发送消息之前对Splunk执行其他检查,或重试失败的消息。您可以跟踪this issue,以便在将来/将来实现此功能时得到通知。

Behind the scenes,接收器只是向Splunk事件收集器发送HTTP POST请求...

要具有所需的行为,您必须实现Serilog.Sinks.Splunk的变体。您可能可以从durable log shipping借用 Serilog.Sinks.Seq的实现,并将无法发送的消息存储在文件中,然后稍后重试...


ps:有趣的是,即使显示如何使用接收器的code sample在发送消息之前也有Thread.Sleep,以便Splunk有机会热身...?