在C#开发的高并发系统中,多个服务实例同时产生大量日志,分散的日志文件会让问题排查变得十分低效,因此需要一套完整的日志聚合方案来统一处理日志。本文介绍的Serilog、OpenTelemetry和ELK组合,能够覆盖日志生成、传输、存储、分析全流程,适配高并发场景的日志处理需求。

核心组件作用说明
这套方案包含三个核心部分,各自承担不同的职责:
- Serilog:C#生态中常用的结构化日志库,支持多种输出目标,能够在应用层高效生成结构化日志,适配高并发场景下的低性能损耗需求。
- OpenTelemetry:可观测性标准框架,负责日志、链路、指标的统一采集和传输,能够将Serilog生成的日志标准化后发送到后端存储。
- ELK:由Elasticsearch、Logstash、Kibana组成的日志处理套件,Elasticsearch负责日志存储和检索,Logstash负责日志过滤和预处理,Kibana负责日志可视化分析。
方案集成步骤
1. 应用中集成Serilog和OpenTelemetry
首先在C#项目中安装必要的NuGet包:
<!-- 项目文件中的PackageReference配置 --> <PackageReference Include="Serilog" Version="3.1.1" /> <PackageReference Include="Serilog.Sinks.OpenTelemetry" Version="1.0.0" /> <PackageReference Include="OpenTelemetry.Extensions.Hosting" Version="1.7.0" />
然后在程序入口配置Serilog和OpenTelemetry:
using Serilog;
using OpenTelemetry;
using OpenTelemetry.Logs;
var builder = WebApplication.CreateBuilder(args);
// 配置Serilog,输出到OpenTelemetry
Log.Logger = new LoggerConfiguration()
.WriteTo.OpenTelemetry(options =>
{
options.Endpoint = "http://192.168.0.1:4317"; // OpenTelemetry Collector的gRPC地址
options.Protocol = Serilog.Sinks.OpenTelemetry.OpenTelemetryProtocol.Grpc;
// 添加自定义资源标签,区分不同服务
options.ResourceAttributes.Add("service.name", "order-service");
options.ResourceAttributes.Add("service.instance.id", Environment.MachineName);
})
.CreateLogger();
builder.Host.UseSerilog();
// 配置OpenTelemetry日志采集
builder.Services.AddOpenTelemetry()
.WithLogging(logging =>
{
logging.AddOtlpExporter(options =>
{
options.Endpoint = new Uri("http://192.168.0.1:4317");
options.Protocol = OpenTelemetry.Exporter.OtlpExportProtocol.Grpc;
});
});
var app = builder.Build();
// 示例接口,模拟高并发场景下的日志记录
app.MapGet("/api/order", () =>
{
Log.Information("收到订单查询请求,请求时间:{RequestTime}", DateTime.Now);
// 模拟业务逻辑
return Results.Ok("订单查询成功");
});
app.Run();
2. 部署OpenTelemetry Collector
OpenTelemetry Collector负责接收应用发送的日志,进行预处理后转发到ELK。以下是基础的配置示例:
receivers:
otlp:
protocols:
grpc:
endpoint: 0.0.0.0:4317
http:
endpoint: 0.0.0.0:4318
processors:
batch:
# 批量处理日志,减少传输次数,适配高并发场景
timeout: 1s
send_batch_size: 1000
exporters:
elasticsearch:
endpoints:
- http://192.168.0.2:9200 # Elasticsearch地址
index: "logs-{service.name}-{yyyy.MM.dd}"
# 映射日志字段,适配Elasticsearch存储
mapping:
message: body
timestamp: time_unix_nano
service:
pipelines:
logs:
receivers: [otlp]
processors: [batch]
exporters: [elasticsearch]
3. 部署ELK套件
Elasticsearch用于存储日志,Kibana用于查询和展示日志。部署完成后,在Kibana中创建索引模式匹配logs-*,即可查看所有服务的聚合日志。
高并发场景优化建议
- Serilog侧开启异步写入,避免日志写入阻塞业务线程,可在配置中添加
.WriteTo.Async(a => a.OpenTelemetry(...))。 - OpenTelemetry Collector的batch处理器根据并发量调整批量大小和超时时间,平衡传输效率和实时性。
- Elasticsearch根据日志量配置合适的分片数,避免单个索引过大影响查询性能。
- 对高频日志添加采样策略,减少不必要的日志传输和存储,降低系统开销。
方案优势总结
这套方案的优势在于全链路标准化,OpenTelemetry作为中间层,后续如果需要替换日志存储组件,只需要调整Collector的配置即可,不需要修改应用代码。同时结构化日志配合Kibana的检索能力,能够快速根据服务名、请求ID、时间范围等条件筛选日志,大幅提升高并发场景下的问题排查效率。
SerilogOpenTelemetryELKC_sharp日志聚合修改时间:2026-07-12 18:36:25