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



我们有一个Windows服务,可以创建一个新线程并每天运行一次计划任务。日志记录是用Serilog完成的,sink是Splunk("Serilog.Sinks.Splunk"(。在成功运行期间,我们将八条信息消息写入日志(Log.Information("((。除了时间戳和整数值之外,每次运行的消息或多或少是相同的。其中四条消息在实际作业任务完成之前记录,四条消息在完成之后记录。

我们发现,有时所有八条消息都出现在 Splunk 中,有时只有最后四条消息(在完成耗时的处理后记录的消息(,有时没有一条消息。

当我们添加另一个接收器,写入文件("Serilog.Sinks.File"(时,我们总是会得到文件中的所有八条消息。

添加Serilog调试日志记录(Serilog.Debugging.SelfLog.Enable(,当日志消息被丢弃时,我们会记录以下调试消息(一次 - 不是每个丢失的消息一个(: "2019-08-30T11:28:03.9029821Z 尝试发送到 https://<>/服务/收集器时收到状态代码"禁止"。 该事件已被丢弃,不会放回队列中。

添加睡眠(System.Threading.Thread.Sleep(((在计划任务中的第一件事是,我们总是在Splunk中的睡眠之后完成日志记录,因此似乎需要一些时间来设置与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);
}
}

有什么方法可以让日志记录在发送消息之前等待打开的连接?或者任何其他选择来避免我们的日志记录以不可预测的方式被丢弃?

在发送消息之前,Serilog.Sinks.Splunk

没有任何现成的功能可以在Splunk 上执行其他检查,或者重试失败的消息。您可以跟踪此问题,以便在将来实施时收到通知。

在后台,接收器只是向 Splunk 事件收集器发送 HTTP POST 请求......

要获得您想要的行为,您必须实现Serilog.Sinks.Splunk的变体。您可能可以从Serilog.Sinks.Seq持久日志传送的实现,并将发送失败的消息存储在文件中,稍后重试......


ps:有趣的是,即使是演示如何使用接收器的代码示例,在发送消息之前也有Thread.Sleep,让 Splunk 有机会热身......🙈

最新更新