c# - 从 Serilog 将事件摄取到 Seq 中的问题
问题描述
我正在开发一个 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.
解决方案
根据您的编辑更新:
程序结束前的最后几条消息似乎是被丢弃的消息。您需要刷新记录器以确保 Serilog 在应用程序有时间退出之前强制并等待任何挂起的日志事件:
public static void Main()
{
try
{
// Program Logic here
}
finally
{
Serilog.Log.CloseAndFlush();
}
}
原答案:
结构化日志记录属性可能会变得非常大,这会导致更大的 HTTP 请求和处理它们的 CPU 需求增加。您的事件“丢失”的原因是因为 Seq(服务器)和 Serilog Sink 都施加了限制,试图缓解这些问题。消息(单个事件或整个批次)可以由客户端或服务器丢弃,具体取决于特定配置和消息/批次大小。注意我说的是“批次”;调用Seq
链接的扩展方法WriteTo
将添加一个PeriodicBatchingSink
(的实现IBatchedLogEventSink
),它包装了SeqSink
. 所以你不需要自己尝试包装它——它已经完成了。
那么如何缓解你的问题呢?首先,您可以更新服务器上的设置。Seq 建议不要这样做,但是有明确的用例,特别是如果您要发送大量属性。您可以在Settings -> System -> Ingestion
下面修改“原始摄取负载限制”和/或“原始事件主体限制”设置。就个人而言,我将前者保留为默认值,并根据我们基于如何配置 Sink 本身所做的一些计算来增加后者:
注意带下划线的警告!确保您了解修改这些设置的含义。
现在在客户端,您有几个选择。Seq
扩展方法有一些参数可以用来调整记录器的行为。
范围 | 默认值 | 描述 |
---|---|---|
eventBodyLimitBytes |
262,144 | 事件的 JSON 表示在被删除而不是发送到 Seq 服务器之前可能占用的最大大小(以字节为单位)。指定null 无限制 |
batchPostingLimit |
1,000 | 单个批次中发布的最大事件数 |
如果批处理事件在序列化为“压缩 JSON”后不适合eventBodyLimitBytes
,则整个批处理将被删除。batchPostingLimit
用于确定在将PeriodBatchingSink
事件发送到内部接收器(执行序列化/丢弃)之前要排队多少消息。您也可以考虑更改最低日志级别,因为它默认为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 将抛出异常。当对 使用Seq
扩展方法时AuditTo
,将DurableSeqSink
使用 a 代替。日志首先保存到磁盘(作为临时存储),然后一次发送到 Seq 。如果您真的必须保证日志消息不会被丢弃(并且如果它们被通知了),那么这就是要走的路。这里有开销;消息必须写入文件,每个事件都需要一个新的 HTTP 请求,并且需要使用try/catch
. 后一点是 IMO 反对这一点的最大原因,特别是如果您使用Microsoft.Extensions.Logging.ILogger
围绕 Serilog 的抽象,因为消费者通常希望日志记录是无异常的。
您还可以使用日志过滤器/LoggingLevelSwitch
和 SerilogFilter.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
推荐阅读
- loops - 使用 react-native-reanimated 创建一个循环
- ffmpeg - ffmpeg 无法转码 DVD ac3 音频流,但 VLC 可以播放
- sparql - 如何进行 SPARQL 查询来计算 OPTIONAL 子句中的唯一节点
- momentjs - week moment.js 的从零开始的格式不可用
- sql - ORACLE SQL:查找列中的最后一行,然后从另一个数据更新数据而不影响旧数据
- mysql - 在 MySQL 中将时间戳转换为本地时间
- python - 运行分裂浏览器时出现 UnboundLocalError
- excel - 如何在excel的每个单元格的第一列中插入第二列数字?
- python - 在范围内也具有像素强度的范围内查找特定坐标像素
- php - 尝试烘烤时出错。#cakephp