〇、前言
前文已经介绍过什么是 Serilog,以及其核心特点,详见:https://www.cnblogs.com/hnzhengfy/p/19167414/Serilog_basic。
本文继续对各种类型的 Sink 进行简单的实践,主题是集中式日志与分析平台 Sinks,供参考。
此类型的 Sinks 常见的有以下五种:
Serilog.Sinks.Seq:将日志发送到 Seq 服务器。Seq 是一个专为 .NET 设计的、易于使用的集中式日志服务器,对结构化日志有原生支持,提供强大的搜索和分析功能。
Serilog.Sinks.ElasticSearch:将日志发送到 Elasticsearch 集群。Elasticsearch 是一个分布式搜索和分析引擎,与 Kibana 结合使用,是构建日志分析平台(ELK Stack)的常用选择。它能完美地索引和查询结构化日志属性。
Serilog.Sinks.Splunk:将日志发送到 Splunk 平台。Splunk 是一个强大的企业级机器数据分析平台,能够高效地处理和分析来自各种来源的结构化和非结构化数据。
Serilog.Sinks.Datadog:将日志发送到 Datadog 平台。Datadog 是一个全面的监控和分析平台,其日志管理功能可以很好地处理 Serilog 的结构化日志。
Serilog.Sinks.NewRelic:将日志发送到 New Relic 平台。New Relic 提供应用性能监控(APM)和日志管理,支持结构化日志的集成。
下边用一个表格简单介绍下它们的现状:
| Sink | 对接平台 | 类型 | 开源/商业 | 典型用户 |
|---|---|---|---|---|
Serilog.Sinks.Seq |
Seq | 本地/私有部署日志服务器 | 社区免费 + 商业版 | .NET 中小团队、初创公司 |
Elastic.Serilog.Sinks |
Elastic(通常搭配 Kibana) | 开源/自建或云服务 | 开源(Apache 2.0) | DevOps 团队、多语言微服务架构 |
Serilog.Sinks.Splunk |
Splunk Enterprise / Cloud | 商业 SIEM & 日志分析平台 | 商业(按数据量计费) | 金融、安全合规、大型企业 |
Serilog.Sinks.Datadog |
Datadog Logs | SaaS 可观测性平台 | 商业(按主机/日志量计费) | 云原生、SRE 团队、全球化公司 |
Serilog.Sinks.NewRelic |
New Relic Logs | SaaS APM + Logs 平台 | 商业(免费层有限) | APM 优先、轻量级日志需求 |
典型应用场景:
| 场景 | 推荐 Sink | 理由 |
|---|---|---|
| .NET 单体或小型微服务,内部部署 | Seq | 快速搭建、无需运维复杂组件、完美支持 C# 结构化日志 |
| 多语言微服务 + 自建日志平台 | Elastic | 统一日志入口,Kibana 强大可视化,社区生态成熟 |
| 上云(AWS/Azure/GCP),追求开箱即用 | Datadog | 与 Metrics、Traces 深度集成,告警、仪表盘体验一流 |
| 金融/医疗/政府,需满足审计与安全合规 | Splunk | 强大的安全信息与事件管理(SIEM)、合规报告能力 |
一句话指南:
| 需求 | 推荐选项 |
|---|---|
| “我是个 .NET 小团队,想要一个简单好用的日志系统” | Seq |
| “我们要构建统一日志平台,支持 Java/Go/.NET 多语言” | Elastic |
| “我们上云了,不想管基础设施,要一体化可观测性” | Datadog |
| “我们是银行,必须满足等保和审计要求” | Splunk |
| “我们已经在用 New Relic 做性能监控,想加点日志” | New Relic |
一、集中式日志与分析平台 Sinks 用法
这些 Sinks 是处理结构化日志的绝佳选择,因为它们专门设计用于存储、索引和查询结构化数据。本文将逐个进行简单示例。
1.1 Serilog.Sinks.Seq:将结构化日志事件发送到 Seq 服务器
Serilog.Sinks.Seq 是 Serilog 官方提供的一个 Sink(日志输出目标),用于将结构化日志事件发送到 Seq 服务器。
Seq 是由 Datalust 开发的一款专为 .NET 和结构化日志设计的日志服务器。它提供:
Web 管理界面(浏览器访问);
强大的结构化日志查询语言(类似 SQL);
实时日志流、仪表盘、告警规则;
支持 Windows、Linux、macOS 和 Docker 部署;
对 Serilog 的结构化日志(如 {UserId}、{DurationMs} 等属性)有原生支持,无需额外解析。
整个流程简单来说就是:用 Serilog 记录带属性的日志 → Seq 自动识别这些属性 → 在 Web 界面上按属性筛选、聚合、告警。
使用的大概步骤:
安装 Seq 服务器(本地或远程);
在 .NET 项目中安装 NuGet 包;
配置 Serilog,添加 Seq Sink;
记录日志并查看 Seq 界面。
下面简单实践一下。
1.1.1 安转 Seq 服务器
先下载服务器安装包,https://datalust.co/download。
Windows 可直接运行 .msi 安装包,例如:Seq-2025.2.14876.msi。安装流程很简单,一直 Next 即可,最后设置下登录信息。
或者从 Docker 启动:
docker run --rm -it -p 5341:80 datalust/seq:latest
安装好之后通过地址访问:http://localhost:5341/。
能看到 Seq 的 UI 界面就说明安装成功了。

1.1.2 创建示例项目并修改代码
创建一个控制台应用程序。
修改 Program.cs 文件(主要就是配置 Serilog 和记录一些模拟日志):
using Serilog;// 配置 Serilog
Log.Logger = new LoggerConfiguration().MinimumLevel.Information().Enrich.WithProperty("Application", "Test12321") // 为每个项目添加一个唯一标识属性.WriteTo.Console() // 可选:输出到控制台.WriteTo.Seq("http://localhost:5341") // 发送到本地 Seq 服务器.CreateLogger();try
{Log.Information("应用程序启动");var userId = 1001;var ipAddress = "1.1.1.1";var durationMs = 4;// 结构化日志:属性自动被 Seq 识别Log.Information("用户 {UserId} 从 {IpAddress} 登录,耗时 {DurationMs} 毫秒",userId, ipAddress, durationMs);Log.Warning("检测到异常登录尝试来自 {IpAddress}", "10.0.0.5");Log.Error(new InvalidOperationException("数据库连接失败"),"无法连接到数据库,服务器 {ServerName}", "DB-PROD-01");Log.Information("应用程序即将关闭");
}
catch (Exception ex)
{Log.Fatal(ex, "应用程序发生未处理异常");
}
finally
{Log.CloseAndFlush(); // 确保日志发送完成
}
1.1.3 测试一下
运行项目,查看 Seq 日志记录情况。
根据应用标识Application="Test12321",查询当前的日志:

注:还有其他筛选,例如通过属性、日志级别、时间区间等等,此处不再一一举例。
1.1.4 高级用法
.WriteTo.Seq(serverUrl: "http://seq.example.com:5341",apiKey: "your-api-key", // 如果 Seq 启用了 API Key(在 Seq 中为某一项目配置的唯一标识)restrictedToMinimumLevel: LogEventLevel.Warning, // 只发送 Warning 及以上batchPostingLimit: 100, // 批量发送数量period: TimeSpan.FromSeconds(2), // 每2秒发送一次compact: true // 使用紧凑 JSON 格式(节省带宽)
)
// 生产环境中建议使用 API Key 来控制访问权限(在 Seq 界面的 Settings --> API Keys 中创建)
1.2 Elastic.Serilog.Sinks:用于将结构化日志直接发送到 Elastic 集群
Elasticsearch 是一个分布式的搜索与分析引擎,特别适合处理大量日志数据。它能高效索引、存储和查询结构化日志,并支持全文搜索、聚合分析等。
Elastic.Serilog.Sinks 主要是 Elastic 官方自己维护的(作者:Elastic and contributors),用于将结构化日志直接发送到 Elasticsearch 集群。它自动将日志条目转换为 JSON 文档,并按时间创建索引(如 log-2025.11.05),便于在 Kibana 中可视化。
优势:
结构化日志:保留日志中的属性(如 UserId、RequestId),便于过滤和分析。
实时查询:通过 Kibana 实时查看日志、创建仪表盘。
自动索引管理:按天/周自动创建索引,避免单索引过大。
高可用支持:支持连接多个 Elasticsearch 节点,具备容错能力。
下边是一个简单的示例来对接 Elasticsearch 服务。
1.2.1 创建一个 WebAPI 项目并安装必要的包
创建一个基于 .net8 的 WebAPI 项目,并安装以下包:
dotnet add package Serilog
dotnet add package Serilog.Sinks.Console
dotnet add package Serilog.AspNetCore
dotnet add package Elastic.Serilog.Sinks
1.2.2 修改 Program.cs
using Elastic.Channels;
using Elastic.Ingest.Elasticsearch;
using Elastic.Ingest.Elasticsearch.DataStreams;
using Elastic.Serilog.Sinks;
using Serilog;
using Serilog.Events;var builder = WebApplication.CreateBuilder(args);// 官网介绍:https://www.elastic.co/docs/reference/ecs/logging/dotnet/serilog-data-shipper
// 配置 Serilog
Log.Logger = new LoggerConfiguration().MinimumLevel.Debug().MinimumLevel.Override("Microsoft", LogEventLevel.Information).Enrich.FromLogContext().WriteTo.Console().WriteTo.Elasticsearch(new[] { new Uri("http://localhost:9200") }, opts =>{opts.DataStream = new DataStreamName("logs", "console-example", "demo");opts.BootstrapMethod = BootstrapMethod.Failure;opts.ConfigureChannel = channelOpts =>{channelOpts.BufferOptions = new BufferOptions{ExportMaxConcurrency = 10};};}, transport =>{// transport.Authentication(new BasicAuthentication(username, password));// transport.Authentication(new ApiKey(base64EncodedApiKey));}).CreateLogger();
// 使用 Serilog 替换默认日志
builder.Host.UseSerilog();
// 其余标准配置
builder.Services.AddControllers();var app = builder.Build();
app.UseAuthorization();
app.MapControllers();
app.Run();
配置 WeatherForecastController.cs 控制器:
using Microsoft.AspNetCore.Mvc;namespace Test.WebAPI.Serilog.WriteToFile.Controllers
{[ApiController][Route("[controller]")]public class WeatherForecastController : ControllerBase{private readonly ILogger<WeatherForecastController> _logger;public WeatherForecastController(ILogger<WeatherForecastController> logger){_logger = logger;}[HttpGet]public IEnumerable<string> Get(){_logger.LogInformation("Fetching weather forecast for {@UserId} at {RequestTime}", "user123", DateTime.UtcNow);return new[] { "Sunny", "Cloudy" };}}public class WeatherForecast{public DateTime Date { get; set; }public int TemperatureC { get; set; }public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);public string? Summary { get; set; }}
}
1.2.3 在 Docker 中安装 Elasticsearch 和 Kibana 并启动 .net 项目进行验证
注:Elasticsearch 和 Kibana 的版本必须严格一致!
// 直接使用启动按钮
// 若本地没有 elasticsearch 会直接先下载再启动
// 安装【elasticsearch】
docker run -d --name elasticsearch ^--privileged ^--net elastic ^-p 9200:9200 -p 9300:9300 ^-e "discovery.type=single-node" ^-e "xpack.security.enabled=false" ^-e "ES_JAVA_OPTS=-Xms512m -Xmx512m" ^--ulimit nofile=65536:65536 ^--ulimit nproc=4096:4096 ^docker.elastic.co/elasticsearch/elasticsearch:9.2.0
// 其中:
// --ulimit nproc=4096:4096:设置最大进程/线程数为 4096
// --privileged:给予容器更多权限(有一定安全风险,仅用于开发)
// --net elastic:网络配置(必须)// 安装【kibana】
// 查看 Kibana 的最新版本:https://www.elastic.co/downloads/kibana
docker run -d ^--name kibana ^--privileged ^--net elastic ^-p 5601:5601 ^-e "discovery__type=single-node" ^-e "xpack__security__enabled=false" ^-e "xpack__encryptedSavedObjects__encryptionKey=abcdefghijklmnopqrstuvwxyz123478" ^-e ELASTICSEARCH_HOSTS=http://elasticsearch:9200 ^-e "ES_JAVA_OPTS=-Xms512m -Xmx512m" ^--ulimit nofile=65536:65536 ^--ulimit nproc=4096:4096 ^docker.elastic.co/kibana/kibana:9.2.0// 安装好后查看容器启动状态
C:\Users\Administrator>docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d3838724a98b docker.elastic.co/kibana/kibana:9.2.0 "/bin/tini -- /usr/l…" 7 seconds ago Up 5 seconds 0.0.0.0:5601->5601/tcp kibana
3c027764c6ed docker.elastic.co/elasticsearch/elasticsearch:9.2.0 "/bin/tini -- /usr/l…" 47 hours ago Up 29 minutes 0.0.0.0:9200->9200/tcp, 0.0.0.0:9300->9300/tcp elasticsearch
// 如果状态 STATUS 不为 Up,则需要查看日志,进一步查明原因
docker logs elasticsearch
// 或者
docker logs kibana
当 elasticsearch 安装好后,可以再浏览器中直接访问,因为在运行容器时已经默认把端口映射加上了,如下图就是启动成功了。

浏览器访问 http://localhost:5601/,查看 Kibana 是否加载正常。第一次加载会先初始化配置。

成功加载:(期间,需要输入六位数的密码,查看日志,查找六位数的密码:docker logs kibana)

连个服务都安装好以后,启动项目写入日志,然后在 Kibana 中查看日志记录。

1.2.4 遇到的几个问题
1)通过 kibana 网址(http://localhost:5601/)访问 elasticsearch 服务时,若访问不到 http://elasticsearch:9200 说明有可能是网络问题
查看网络配置:docker network inspect elastic
查看输出中的 Containers 部分,应该同时包含 elasticsearch 和 kibana
例如:
"Containers": {0
"a1b2c3...": {
"Name": "elasticsearch",
"IPv4Address": "172.18.0.2/16"
},
"d4e5f6...": {
"Name": "kibana",
"IPv4Address": "172.18.0.3/16"
}
}
2)内存问题,docker 中服务无法启动
// 查看 elasticsearch 日志
C:\Users\Administrator>docker logs elasticsearch
[0.002s][warning][os,thread] Failed to start thread "ArchiveWorkerThread" - pthread_create failed (EPERM) for attributes: stacksize: 1024k, guardsize: 4k, detached.
Error occurred during initialization of VM
Unable to create archive worker: unable to create native thread: possibly out of memory or process/resource limits reached// 想在 Docker Desktop 中修改,但提示:
Resources Advanced
You are using the WSL 2 backend, so resource limits are managed by Windows.
You can configure limits on the memory, CPU, and swap size allocated to WSL 2 in a .wslconfig file.
Docker Desktop 使用的是 WSL2 后端,资源限制(内存、CPU 等)不再通过 Docker Desktop GUI 设置,而是通过 Windows 的 .wslconfig 文件控制。这是 Windows 10/11 + WSL2 + Docker Desktop 的新行为(尤其在较新版本中),GUI 中的 “Resources” 设置可能被禁用或仅作参考。
打开 Windows 文件资源管理器,进入“用户”主目录(通常是:C:\Users\Administrator)。
创建一个名为 .wslconfig 的文件(注意前面有个点)。
注:如果看不到文件扩展名,请在“查看”选项卡中勾选“文件扩展名”和“隐藏的项目”。
文件内容示例(推荐用于运行 Elasticsearch):
[wsl2]
memory=4GB # 分配给所有 WSL2 发行版的总内存
processors=2 # CPU 核心数
swap=2GB # 交换空间
localhostForwarding=true
然后查看是否修改成功:
C:\Users\Administrator>wsl --shutdown
C:\Users\Administrator>wsl cat /proc/meminfo | findstr MemTotal
MemTotal: 4026076 kB
如果重新新建容器,还是报错内存不足,说明问题不是内存总量不足,而是线程创建被系统策略阻止。在 WSL2 中,这通常是因为 ulimit(用户资源限制)过低,特别是 max user processes(nproc)。
如何解决:使用 --privileged + 启动脚本(不完美但有效),在上文的启动语句中已经使用。
1.3 Serilog.Sinks.Datadog.Logs:非常适合微服务和云原生架构【收费】
注意:Serilog.Sinks.Datadog 已被遗弃,推荐使用由 Datadog 官方维护的 Serilog.Sinks.Datadog.Logs。
Serilog.Sinks.Datadog.Logs 可将 Serilog 产生的结构化日志实时发送到 Datadog 的日志摄入 API。并自动处理认证、批量发送、重试、元数据注入(如服务名、环境等)。
下边开始简单实践一下,目的是通过配置 Serilog 将日志同时输出到控制台和 Datadog。
1.3.1 创建一个控制台应用程序并引用必要的包
创建一个控制台应用程序后,在项目中添加如下包:
dotnet add package Serilog.AspNetCore
dotnet add package Serilog.Sinks.Console
dotnet add package Serilog.Sinks.Datadog.Logs
若同时使用 Datadog APM(分布式追踪),需要安装专门的包:Datadog.Trace,然后再 Main 开头加上Datadog.Trace.Tracer.Initialize();,Serilog 会自动注入 dd.trace_id 和 dd.span_id,实现日志与追踪关联。
1.3.2 修改 Program.cs
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Logging;
using Serilog;
using Serilog.Events;
using Serilog.Sinks.Datadog.Logs;
using System.Data;
using System.Text;Serilog.Debugging.SelfLog.Enable(Console.Error); // 打印出详细日志信息var builder = WebApplication.CreateBuilder(args);string apiKey = "af164c7b92542f64d4e0614079536d7d";
// 配置 Serilog
Log.Logger = new LoggerConfiguration().MinimumLevel.Information().WriteTo.Console() // 本地控制台输出(可选).WriteTo.DatadogLogs(apiKey,service: "chengzj-service-cz", host: "chengzj-host-cz"//, service: "chengzj-service-zfy" // 模拟多负载时,不同服务向同一地址发送日志//, host: "chengzj-host-zfy", configuration: new DatadogConfiguration(// 默认用的是 US1 站点(http-intake.logs.datadoghq.com)// 因此需要指定 US5 站点地址url: "https://http-intake.logs.us5.datadoghq.com"// EU 欧洲站点地址:https://http-intake.logs.datadoghq.eu)).CreateLogger();builder.Host.UseSerilog(); // 将 Serilog 注入到 Hostvar app = builder.Build();// 日志记录测试
app.MapGet("/", (ILogger<Program> logger) =>
{// 发送结构化日志Log.Error("User {@User} logged in from {IpAddress}",new { Id = 123, Name = "Alice", Role = "Admin" },"192.168.1.100");logger.LogInformation("User {@User} logged in from {IpAddress}",new { Id = 123, Name = "Alice", Role = "Admin" },"192.168.1.100");return "Hello from .NET 8 with Datadog!";
});// 手动用于测试目标地址是否正常访问
app.MapGet("/test", async () =>
{using var client = new HttpClient();client.DefaultRequestHeaders.Add("DD-API-KEY", apiKey);var json = @"[{""message"":""Test from C#""}]";var content = new StringContent(json, Encoding.UTF8, "application/json");var response = await client.PostAsync("https://http-intake.logs.us5.datadoghq.com/v1/input",content);return $"Status: {response.StatusCode}, Body: {await response.Content.ReadAsStringAsync()}";
});app.Run("http://localhost:5100");
1.3.3 运行控制台应用程序测试日志发送
运行项目,查看日志写入情况,查看地址:https://us5.datadoghq.com/logs/livetail。
然后调用日志记录接口:http://localhost:5100,调用直接发送日志请求的测试接口:http://localhost:5100/test。
结构化日志记录如下图:

注意:Datadog 并非免费软件,通常为 14 天,最长也就 30 天。因此,在选用时要着重考虑下成本问题。
对于 Datadog,其 Agent 是最基础也是最常用。它的存在,就像给操作系统装了个"智能小助手"。Datadog Agent会自动收集服务器、容器、数据库等的指标,不需要太多配置就能开始监控。安装后,就能看到CPU、内存、网络等基础指标,简直像给系统装了"健康监测仪"。Datadog 还可以与云服务集成,特别是Azure。现在几乎每个企业都用云,Datadog 和 Azure 的集成特别方便。通过 Azure 门户就能一键订阅 Datadog,然后自动收集所有 Azure 资源的指标和日志,再也不用在多个平台间切换了。Datadog 还是有很多可讨论的地方,等后续再单独列举吧。
另外,还有两种常见的日志记录方式,就是 Splunk 平台、New Relic 平台,本文就暂时略过了,如下:
Serilog.Sinks.Splunk: 将日志发送到 Splunk 平台。Splunk 是一个强大的企业级机器数据分析平台,能够高效地处理和分析来自各种来源的结构化和非结构化数据。
Serilog.Sinks.NewRelic: 将日志发送到 New Relic 平台。New Relic 提供应用性能监控(APM)和日志管理,支持结构化日志的集成。