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

相关推荐
r***12382 小时前
Spring boot启动原理及相关组件
数据库·spring boot·后端
m***11902 小时前
【SpringBoot】Spring Boot 项目的打包配置
java·spring boot·后端
李慕婉学姐2 小时前
Springboot剪纸数字博物馆系统6wd19a3a(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
java·spring boot·后端
追逐时光者2 小时前
精选 5 款 .NET 开源、实用的商城系统(Shop),快速商城二开利器!
后端·.net
追逐时光者3 小时前
一款基于 .NET + 计算机视觉技术开源免费、功能强大的原神智能辅助工具,一键解放双手!
后端·.net
90后小陈老师3 小时前
用户管理系统 05 实现后端注册功能 | Java新手实战 | 最小架构 | 期末实训 | Java+SpringBoot+Vue3
java·开发语言·spring boot·后端·spring·maven·mybatis
k***85843 小时前
【SpringBoot】【log】 自定义logback日志配置
android·前端·后端
canonical_entropy4 小时前
可逆计算的方法论来源
后端·低代码
数据知道5 小时前
【Flask】一文掌握 Flask 基础用法
数据库·后端·python·flask·python web