Serilog 发送日志到 Logstash 应该用哪个 Sink?
推荐 Serilog.Sinks.Network 的 TCP sink 配合 JSON 格式化器发送到 Logstash 的 tcp 输入;也可用 HTTP sink 或先写文件再由采集器转发。本文给出配置示例。
推荐方案:用 Serilog.Sinks.Network 包的 TCP sink,搭配 JSON 格式化器,把结构化日志直接发到 Logstash 的 tcp 输入端口——网络直发省去文件中转,TCP 比 UDP 可靠;如果对投递可靠性要求高,更稳妥的做法是写本地 JSON 文件,由采集代理转发。
方案一:TCP 直发
安装包:
dotnet add package Serilog.Sinks.Network
配置 Serilog:
using Serilog;
Log.Logger = new LoggerConfiguration()
.WriteTo.Console()
.WriteTo.Tcp("logstash-host", 5044, new Serilog.Formatting.Json.JsonFormatter())
.CreateLogger();
Log.Information("用户 {UserId} 登录成功", 42);
Logstash 侧对应输入:
input {
tcp {
port => 5044
codec => json_lines
}
}
JSON 格式化保证结构化字段(如 UserId)原样进 ES,而不是被揉成一团文本。
方案二:写文件 + 采集转发(生产更稳)
.WriteTo.File(new Serilog.Formatting.Json.JsonFormatter(),
"logs/app-.json", rollingInterval: RollingInterval.Day)
应用只管写本地文件,转发、重试、背压全部由采集代理(如 Filebeat)负责,网络抖动不丢日志,应用也不依赖 Logstash 可用性。
常见坑
- UDP 会丢包:内网低负载可用,跨网络务必 TCP。
- 换行分隔:Logstash 用
json_linescodec 时,每条 JSON 必须以换行结尾,Network sink 默认如此。 - 断连缓冲:TCP sink 在 Logstash 不可用时默认丢弃,配
WriteTo.Async加缓冲包装可降低影响。
观测云对照
.NET 应用日志直连观测云。 Serilog 输出 JSON 到文件或 stdout 后,由 DataKit 采集;容器化部署时直接打 stdout 最省心。配合 APM .NET 探针,日志可与调用链关联分析。
常见问题(FAQ)
Q:Serilog 有专门的 Logstash sink 吗?
A:社区有 Serilog.Sinks.Logstash(HTTP/UDP),但维护活跃度一般,通用做法仍是 Network TCP + json_lines。
Q:Logstash 端收到的是一行多个 JSON 粘在一起怎么办?
A:codec 要用 json_lines 而非 json;json codec 期望一个完整 JSON 文档一条消息。
Q:想保留 Serilog 的消息模板属性怎么办?
A:用 JsonFormatter(或 CompactJsonFormatter 输出 CLEF 格式),属性会作为顶层字段写入 JSON。