【问题标题】:Problems ingesting events into Seq from Serilog从 Serilog 将事件摄取到 Seq 中的问题
【发布时间】:2021-02-04 07:52:31
【问题描述】:

我正在开发一个 C# 应用程序,该应用程序通过 Serilog (Serilog.Sinks.Seq) 在远程 Seq Sink 上发送日志。在我添加更多日志之前它运行良好;之后,它只是将一些日志发送到 seq。我测试了文件接收器,但它没有任何问题,并将所有日志写入文件,但 seq 仍然有同样的问题。我什至在本地计算机上测试了 Seq,但没有利润。
所以我安装了 Serilog.Sinks.PeriodicBatching 希望能解决这个问题。但不幸的是,我没有找到任何文档或示例如何在我的项目中配置和启用它。我发现的唯一代码是https://github.com/serilog/serilog-sinks-periodicbatching,我不明白。有人知道如何使用它来解决 Seq 的这个问题吗?我需要一个简单的例子。
我正在使用最新版本的 Serilog 和 PeriodicBatching。
更新 1:
这是正确生成的文件日志。在 seq 中,最后三个日志被删除。

2021-02-06 09:45:36.164 +03:30 [INF] ⠀⠀⠀⠀⠀|  
2021-02-06 09:45:36.180 +03:30 [INF] Application Start.  
2021-02-06 09:45:36.180 +03:30 [ERR] It is a fresh OS  
System.ArgumentNullException: Value cannot be null.
Parameter name: value
   at Newtonsoft.Json.JsonConvert.DeserializeObject(String value, Type type, JsonSerializerSettings settings)
   at Newtonsoft.Json.JsonConvert.DeserializeObject[T](String value, JsonSerializerSettings settings)
   at SenderConsole.Program.scanClientAndSendIfDifferent() in D:\Programing\SysWatch\SenderConsole\Program.cs:line 434  
2021-02-06 09:45:36.195 +03:30 [DBG] getCurrentClientConfig() Started.  
2021-02-06 09:45:36.289 +03:30 [DBG] getCurrentClientConfig()==> CpuChanges  
2021-02-06 09:45:36.305 +03:30 [DBG] getCurrentClientConfig()==> StorageChanges  
2021-02-06 09:45:36.383 +03:30 [DBG] getCurrentClientConfig()==> RamChanges  
2021-02-06 09:45:36.398 +03:30 [DBG] getCurrentClientConfig()==> MotherboardChanges  
2021-02-06 09:45:36.414 +03:30 [DBG] getCurrentClientConfig()==> OsChanges  
2021-02-06 09:45:36.492 +03:30 [DBG] getCurrentClientConfig()==> NicChanges  
2021-02-06 09:45:36.679 +03:30 [DBG] getCurrentClientConfig()==> PrinterChanges  
2021-02-06 09:45:36.695 +03:30 [DBG] getCurrentClientConfig()==> DomainChanges  
2021-02-06 09:45:36.883 +03:30 [DBG] getCurrentClientConfig()==> iSMBIOSChanges  
2021-02-06 09:45:36.914 +03:30 [DBG] getCurrentClientConfig()==> AppChanges  
2021-02-06 09:45:36.929 +03:30 [DBG] getCurrentClientConfig()==> AntivirusChanges  
2021-02-06 09:45:36.929 +03:30 [DBG] getCurrentClientConfig() Ended.  
2021-02-06 09:45:36.929 +03:30 [DBG] configsAreDifferent() Started.  
2021-02-06 09:45:36.929 +03:30 [INF] Configs are different.  
2021-02-06 09:45:36.929 +03:30 [DBG] serializeByJson() Started.  
2021-02-06 09:45:37.148 +03:30 [DBG] serializeByJson() Ended.  
2021-02-06 09:45:39.210 +03:30 [FTL] Unable to connect to the remote server  
2021-02-06 09:45:39.210 +03:30 [INF] Sent to DB.  
2021-02-06 09:45:39.210 +03:30 [INF] Application End.  

【问题讨论】:

  • Seq 在网站中的设置决定了它将接受的最大负载大小。根据您的结构化日志属性,它们可能会被删除。我发现我必须增加我的相当大。 seq sink 中还有客户端设置,您可以使用它来控制批次的大小。减少消息数量和批量大小,以便服务器中的设置为倍数可能会对您有所帮助。它帮助了我,我的日志不再被丢弃。如果您查看它的来源,seq 接收器已经是一个定期批处理接收器。
  • 感谢@pinkfloydx33 的评论。如何在客户端配置批处理?
  • 调用WriteTo.Seq时有几个可选属性,你可以从那里开始。我在手机上,所以不知道在我的头上
  • 另外,您的问题非常令人困惑,因为 PeriodicBatchingSink 是一个内部细节(当您昨天询问并删除了该问题时,这是人们无法弄清楚您在问什么的主要原因 - 的解决此类问题的方法是编辑问题,而不是删除它!)。

标签: c# logging serilog seq


【解决方案1】:

根据您的修改进行更新:

您的程序结束前的最后几条消息似乎是被丢弃的消息。您需要刷新记录器以确保 Serilog 在应用程序有时间退出之前强制并等待任何待处理的日志事件:

public static void Main() 
{
   try
   {
       // Program Logic here
   } 
   finally
   {
       Serilog.Log.CloseAndFlush(); 
   } 
} 

原答案:

结构化日志记录属性可能会变得非常大,这会导致更大的 HTTP 请求和处理它们的 CPU 需求增加。您的事件“丢失”的原因是因为 Seq(服务器)和 Serilog Sink 都施加了限制,试图缓解这些问题。消息(单个事件或整个批次)可以由客户端或服务器丢弃,具体取决于特定配置和消息/批次大小。注意我说的是“批次”;调用与WriteTo 链接的Seq 扩展方法将添加一个PeriodicBatchingSinkIBatchedLogEventSink 的实现),它包装SeqSink。所以你不需要自己尝试包装它——它已经完成了。

那么你如何缓解你的问题呢?首先,您可以更新服务器上的设置。 Seq 建议不要这样做,但是有明确的用例,特别是如果您要发送大量属性。在Settings -> System -> Ingestion 下,您可以修改“原始摄取负载限制”和/或“原始事件主体限制”设置。就个人而言,我将前者保留为默认值,并根据我们根据如何配置 Sink 本身所做的一些计算来增加后者:

注意带下划线的警告!确保您了解修改这些设置的含义。

现在在客户端,您有几个选项。 Seq 扩展方法有一些参数可用于调整记录器的行为。

Parameter Default Value Description
eventBodyLimitBytes 262,144 The maximum size, in bytes, that the JSON representation of an event may take before it is dropped rather than being sent to the Seq server. Specify null for no limit
batchPostingLimit 1,000 The maximum number of events to post in a single batch

如果 batched 事件在序列化为“压缩 JSON”后不适合 eventBodyLimitBytes,则将删除 整个 批次。 batchPostingLimitPeriodBatchingSink 用于确定在将事件发送到内部接收器(执行序列化/丢弃)之前要排队的消息数量。您还可以考虑更改最低日志级别,因为它默认为 Verbose 或传入 LoggingLevelSwitch

var maxSizeBytes = 512 * 1024; // 512KB, double the default
var batchLimit = 100; // 1/10 the default
logger.WriteTo.Seq(
    "http://seq.server.com", 
    eventBodyLimitBytes: maxSizeBytes, 
    batchPostingLimit: batchLimit, 
    restrictedToMinimumLevel: LogEventLevel.Information
);

配置较小的批处理大小可能会降低您超出字节限制的机会,但这会导致发送 更多 个 HTTP 请求,这可能是其自身的问题。现在请记住,您还需要坚持服务器的配置;您的组合事件大小必须小于“原始摄取负载限制”,以确保不会丢弃整个批次,并且单个事件必须小于“原始事件主体限制”。

由于我对您的实际事件一无所知,因此无法就此处的适当设置提供建议。我只能为您指出正确的方向。我只能说,您应该根据服务器设置、对事件(及其附加属性)的了解以及您的业务需求执行一些有意义的计算:

您的另一个选择是使用“审计”接收器。在这种模式下,如果日志消息无法传输到目标介质,Serilog 将抛出异常。当对AuditTo 使用Seq 扩展方法时,将使用DurableSeqSink。日志首先保存到磁盘(作为临时存储),然后一次发送到 Seq。如果您真的必须保证日志消息不会被丢弃(并且如果它们被通知了),那么这就是要走的路。这里有开销;消息必须写入文件,每个事件都需要一个新的 HTTP 请求并且您需要使用 try/catch 保护所有日志记录语句。后一点是 IMO 反对这一点的最大原因,特别是如果您在 Serilog 周围使用 Microsoft.Extensions.Logging.ILogger 抽象,因为消费者通常希望日志记录是无异常的。

您还可以使用日志过滤器/LoggingLevelSwitch 和 Serilog 的Filter.ByExcluding 来控制将要发送的消息。此外,您还可以考虑调整解构深度和大小,以确保嵌套属性和集合仅被序列化到最大大小。

logger.Destructure.ToMaximumDepth(5) // default 10
      .Destructure.ToMaximumStringLength(1000) // made up value, default is int.MaxValue
      .Destructure.ToMaximumCollectionCount(10) // made up, default is int.MaxValue

【讨论】:

  • 感谢您的回答。我做了你说的,但没有工作。我将更新我的问题以将摘要日志写入文件和 Seq。
  • 当它运行时没有缓慢的异常,它消化所有的日志没有问题。
  • @MahmoodJenami 您是否在程序结束前刷新记录器?如果 Serilog 没有时间交付批处理,则丢弃最后几条消息是有意义的。见我上面的编辑
  • 你拯救了我的一天@pinkfloydx33。 Serilog.Log.CloseAndFlush() 为我工作。非常感谢。
  • @MahmoodJenami 很高兴为您提供帮助。但请记住其余的答案。如果大小变得太大或网络请求失败等,Seq 可以丢弃消息/批次
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多