Serilog 日志库简单实践(三)集中式日志与分析平台 Sinks(.net8)

〇、前言

前文已经介绍过什么是 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 注入到 Host

var 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)和日志管理,支持结构化日志的集成。

相关推荐
星辰徐哥18 小时前
Spring Boot 微服务架构设计与实现
spring boot·后端·微服务
星辰徐哥18 小时前
Spring Boot 数据导入导出与报表生成
spring boot·后端·ui
明夜之约18 小时前
Spring Boot 自动装配源码
java·spring boot·后端
Leaton Lee18 小时前
Spring Boot分层架构详解:从Controller到Service再到Mapper的完整流程
java·spring boot·后端·架构
Micro麦可乐18 小时前
Spring Boot 实战:从零设计一个短链系统(含完整代码与数据库设计)
数据库·spring boot·后端·哈希算法·雪花算法·短链系统
Jinkxs18 小时前
Resilience4j- 与 Spring Boot 快速集成:自动配置与基础注解使用
java·spring boot·后端
毕设源码_郑学姐18 小时前
计算机毕业设计springboot网络相册设计与实现 基于Spring Boot框架的在线相册管理系统开发与应用 Spring Boot驱动的网络影集设计与实践
spring boot·后端·课程设计
辣机小司18 小时前
【踩坑记录:Spring Boot 配置文件读取值不一致?警惕 YAML 的“八进制陷阱”与 SnakeYAML 版本之谜】
java·spring boot·后端·yaml·踩坑记录
码农阿豪18 小时前
从零到一:Spring Boot快速接入金仓数据库实战
数据库·spring boot·后端
追逐时光者18 小时前
一个基于 .NET 与 Avalonia 构建、面向 TrinityCore 的开源 WoW 数据库编辑器
后端·.net