C#.NET serilog 详解(c# repository)
ztj100 2025-07-24 23:24 24 浏览 0 评论
简介
Serilog 是 .NET 平台中非常流行且强大的结构化日志库,其最大特点是“结构化日志记录(Structured Logging)”,支持通过键值对记录丰富的上下文信息,并且拥有强大的 Sink 插件系统,支持写入控制台、文件、数据库、Elasticsearch、Seq 等。
Serilog 核心概念
概念 | 说明 |
Logger | 日志记录器实例 |
Sink | 日志的输出目标,如 Console、File、Elasticsearch 等 |
Enrichment | 日志信息的丰富,比如自动记录线程ID、机器名等上下文信息 |
Filter | 日志的筛选器 |
Structured Logging | 日志以键值对形式记录,便于搜索和分析 |
安装 Serilog(NuGet 包)
dotnet add package Serilog.AspNetCore
dotnet add package Serilog.Sinks.Console
dotnet add package Serilog.Sinks.File
dotnet add package Serilog.Sinks.Async
基础配置示例
using Serilog;
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
.Enrich.FromLogContext()
.WriteTo.Console()
.WriteTo.File("Logs/log.txt", rollingInterval: RollingInterval.Day)
.CreateLogger();
try
{
Log.Information("Starting up");
// 启动主程序或 ASP.NET Core 应用
}
catch (Exception ex)
{
Log.Fatal(ex, "Application start-up failed");
}
finally
{
Log.CloseAndFlush();
}
ASP.NET Core 集成方式
using Serilog;
var builder = WebApplication.CreateBuilder(args);
// 配置 Serilog 替换默认日志
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(builder.Configuration)
.Enrich.FromLogContext()
.WriteTo.Console()
.WriteTo.File("Logs/log-.txt", rollingInterval: RollingInterval.Day)
.CreateLogger();
builder.Host.UseSerilog(); // 使用 Serilog
builder.Services.AddControllers();
var app = builder.Build();
app.MapControllers();
app.Run();
appsettings.json 配置方式
"Serilog": {
"Using": [ "Serilog.Sinks.Console", "Serilog.Sinks.File" ],
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft": "Warning",
"System": "Warning"
}
},
"Enrich": [ "FromLogContext", "WithThreadId" ],
"WriteTo": [
{
"Name": "Console"
},
{
"Name": "File",
"Args": {
"path": "Logs/log-.txt",
"rollingInterval": "Day",
"outputTemplate": "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}"
}
}
]
}
配合 NuGet 包:
dotnet add package Serilog.Settings.Configuration
Serilog Sink 示例
Sink 名称 | 说明 |
Serilog.Sinks.Console | 输出到控制台 |
Serilog.Sinks.File | 输出到文件 |
Serilog.Sinks.Seq | 输出到 Seq 可视化平台 |
Serilog.Sinks.Elasticsearch | 输出到 Elasticsearch |
Serilog.Sinks.Async | 异步包装器 |
Serilog.Sinks.MSSqlServer | 写入 SQL Server |
基本用法
基本结构化日志
var orderId = 123;
var customerId = 456;
// 结构化日志记录
Log.Information("处理订单 {OrderId} 来自客户 {CustomerId}", orderId, customerId);
// 输出示例(JSON 格式):
// {
// "OrderId": 123,
// "CustomerId": 456,
// "Message": "处理订单 123 来自客户 456",
// "Level": "Information"
// }
复杂对象序列化
var order = new Order { Id = 123, Products = new List<string> { "Book", "Pen" } };
Log.Information("创建订单 {@Order}", order);
// 输出: 创建订单 {"Id": 123, "Products": ["Book", "Pen"]}
上下文丰富(Enrichers)
// 为当前作用域添加属性
using (LogContext.PushProperty("RequestId", Guid.NewGuid()))
{
Log.Information("处理请求");
// 所有日志自动附加 RequestId 属性
}
// 添加全局属性
Log.Logger = new LoggerConfiguration()
.Enrich.WithMachineName()
.Enrich.WithEnvironmentUserName()
.CreateLogger();
// 添加临时上下文
using (LogContext.PushProperty("RequestId", Guid.NewGuid())) {
Log.Information("处理请求");
}
常用 Enrichers
.Enrich.WithProperty("AppVersion", "1.0.0")
.Enrich.FromLogContext()
.Enrich.WithThreadId()
文件滚动
按日期或大小滚动日志文件:
.WriteTo.File("logs/app-.log",
rollingInterval: RollingInterval.Day,
fileSizeLimitBytes: 10_000_000,
retainedFileCountLimit: 30)
- rollingInterval:按天滚动。
- fileSizeLimitBytes:限制文件大小(10MB)。
- retainedFileCountLimit:保留 30 个文件。
数据库 Sink
dotnet add package Serilog.Sinks.MSSqlServer
.WriteTo.MSSqlServer(
connectionString: "Server=.;Database=Logs;Trusted_Connection=True;",
sinkOptions: new MSSqlServerSinkOptions { TableName = "Logs" })
过滤日志
通过过滤器控制日志:
.Filter.ByExcluding(logEvent => logEvent.Properties.ContainsKey("SensitiveData"))
JSON 配置
"Filter": [
{
"Name": "ByExcluding",
"Args": {
"expression": "SourceContext = 'Microsoft.*'"
}
}
]
配置 HTTP 上下文:
高级用法
动态日志级别
var levelSwitch = new LoggingLevelSwitch(LogEventLevel.Information);
Log.Logger = new LoggerConfiguration()
.MinimumLevel.ControlledBy(levelSwitch)
.WriteTo.Console()
.CreateLogger();
// 运行时调整级别
levelSwitch.MinimumLevel = LogEventLevel.Debug;
自定义输出模板
.WriteTo.Console(outputTemplate:
"[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj} {Properties}{NewLine}{Exception}")
错误日志特殊处理
.WriteTo.Logger(lc => lc
.Filter.ByIncludingOnly(e => e.Level == LogEventLevel.Error)
.WriteTo.File("logs/errors.txt"))
请求日志中间件
app.UseSerilogRequestLogging(options =>
{
options.EnrichDiagnosticContext = (diagnosticContext, httpContext) =>
{
diagnosticContext.Set("User", httpContext.User.Identity.Name);
diagnosticContext.Set("ClientIP", httpContext.Connection.RemoteIpAddress);
};
});
异步日志
.WriteTo.Async(a => a.File("logs/async.log"))
批量写入
// 使用 PeriodicBatchingSink 实现批处理
Log.Logger = new LoggerConfiguration()
.WriteTo.Console()
.WriteTo.PeriodicBatchingSink(
new HttpSink("https://logserver/api/logs"),
batchSizeLimit: 100,
period: TimeSpan.FromSeconds(2))
.CreateLogger();
使用配置文件初始化
using Serilog;
using Serilog.Settings.Configuration;
var configuration = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.Build();
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(configuration)
.CreateLogger();
条件性日志记录
Log.Logger = new LoggerConfiguration()
.WriteTo.Logger(lc => lc
.Filter.ByIncludingOnly(e => e.Level == LogEventLevel.Error)
.WriteTo.File("logs/errors.log"))
.WriteTo.Logger(lc => lc
.Filter.ByIncludingOnly(e => e.Level == LogEventLevel.Information)
.WriteTo.Console())
.CreateLogger();
级别动态控制
.MinimumLevel.Override("Microsoft", LogEventLevel.Warning) // 抑制第三方库日志
轻量级序列化
.WriteTo.File(new CompactJsonFormatter(), "logs/compact.json") // 节省存储
异步批处理配置
.WriteTo.Async(a => a.Elasticsearch(), batchSize: 1000)
参数调优:
- batchSize:根据网络延迟调整(建议 500-5000)
- blockWhenFull:队列满时阻塞而非丢弃
零分配渲染(ZeroAllocation)
var log = new LoggerConfiguration()
.Destructure.ByTransforming<User>(u => new { u.Id, u.Name })
.CreateLogger();
// 避免 ToString() 分配
Log.Information("用户 {@User} 登录", user);
自定义 Sink 开发
public class CustomSink : ILogEventSink {
public void Emit(LogEvent logEvent) {
var json = JsonConvert.SerializeObject(logEvent.Properties);
SendToQueue(queue, json); // 写入消息队列
}
}
// 注册
.WriteTo.Sink(new CustomSink())
故障转移机制
.WriteTo.Conditional(
e => IsElasticAlive(),
wt => wt.Elasticsearch(),
wt => wt.File("fallback.log")
)
过滤日志
通过过滤器控制日志
.Filter.ByExcluding(logEvent => logEvent.Properties.ContainsKey("SensitiveData"))
JSON 配置
"Filter": [
{
"Name": "ByExcluding",
"Args": {
"expression": "SourceContext = 'Microsoft.*'"
}
}
]
相关推荐
- Linux集群自动化监控系统Zabbix集群搭建到实战
-
自动化监控系统...
- systemd是什么如何使用_systemd/system
-
systemd是什么如何使用简介Systemd是一个在现代Linux发行版中广泛使用的系统和服务管理器。它负责启动系统并管理系统中运行的服务和进程。使用管理服务systemd可以用来启动、停止、...
- Linux服务器日常巡检脚本分享_linux服务器监控脚本
-
Linux系统日常巡检脚本,巡检内容包含了,磁盘,...
- 7,MySQL管理员用户管理_mysql 管理员用户
-
一、首次设置密码1.初始化时设置(推荐)mysqld--initialize--user=mysql--datadir=/data/3306/data--basedir=/usr/local...
- Python数据库编程教程:第 1 章 数据库基础与 Python 连接入门
-
1.1数据库的核心概念在开始Python数据库编程之前,我们需要先理解几个核心概念。数据库(Database)是按照数据结构来组织、存储和管理数据的仓库,它就像一个电子化的文件柜,能让我们高效...
- Linux自定义开机自启动服务脚本_linux添加开机自启动脚本
-
设置WGCloud开机自动启动服务init.d目录下新建脚本在/etc/rc.d/init.d新建启动脚本wgcloudstart.sh,内容如下...
- linux系统启动流程和服务管理,带你进去系统的世界
-
Linux启动流程Rhel6启动过程:开机自检bios-->MBR引导-->GRUB菜单-->加载内核-->init进程初始化Rhel7启动过程:开机自检BIOS-->M...
- CentOS7系统如何修改主机名_centos更改主机名称
-
请关注本头条号,每天坚持更新原创干货技术文章。如需学习视频,请在微信搜索公众号“智传网优”直接开始自助视频学习1.前言本文将讲解CentOS7系统如何修改主机名。...
- 前端工程师需要熟悉的Linux服务器(SSH 终端操作)指令
-
在Linux服务器管理中,SSH(SecureShell)是远程操作的核心工具。以下是SSH终端操作的常用命令和技巧,涵盖连接、文件操作、系统管理等场景:一、SSH连接服务器1.基本连接...
- Linux开机自启服务完全指南:3步搞定系统服务管理器配置
-
为什么需要配置开机自启?想象一下:电商服务器重启后,MySQL和Nginx没自动启动,整个网站瘫痪!这就是为什么开机自启是Linux运维的必备技能。自启服务能确保核心程序在系统启动时自动运行,避免人工...
- Kubernetes 高可用(HA)集群部署指南
-
Kubernetes高可用(HA)集群部署指南本指南涵盖从概念理解、架构选择,到kubeadm高可用部署、生产优化、监控备份和运维的全流程,适用于希望搭建稳定、生产级Kubernetes集群...
- Linux项目开发,你必须了解Systemd服务!
-
1.Systemd简介...
- Linux系统systemd服务管理工具使用技巧
-
简介:在Linux系统里,systemd就像是所有进程的“源头”,它可是系统中PID值为1的进程哟。systemd其实是一堆工具的组合,它的作用可不止是启动操作系统这么简单,像后台服务...
- Linux下NetworkManager和network的和平共处
-
简介我们在使用CentoOS系统时偶尔会遇到配置都正确但network启动不了的问题,这问题经常是由NetworkManager引起的,关闭NetworkManage并取消开机启动network就能正...
你 发表评论:
欢迎- 一周热门
-
-
MySQL中这14个小玩意,让人眼前一亮!
-
Linux下NetworkManager和network的和平共处
-
Kubernetes 高可用(HA)集群部署指南
-
linux系统启动流程和服务管理,带你进去系统的世界
-
7,MySQL管理员用户管理_mysql 管理员用户
-
旗舰机新标杆 OPPO Find X2系列正式发布 售价5499元起
-
面试官:使用int类型做加减操作,是线程安全吗
-
C++编程知识:ToString()字符串转换你用正确了吗?
-
【Spring Boot】WebSocket 的 6 种集成方式
-
PyTorch 深度学习实战(26):多目标强化学习Multi-Objective RL
-
- 最近发表
-
- Linux集群自动化监控系统Zabbix集群搭建到实战
- systemd是什么如何使用_systemd/system
- Linux服务器日常巡检脚本分享_linux服务器监控脚本
- 7,MySQL管理员用户管理_mysql 管理员用户
- Python数据库编程教程:第 1 章 数据库基础与 Python 连接入门
- Linux自定义开机自启动服务脚本_linux添加开机自启动脚本
- linux系统启动流程和服务管理,带你进去系统的世界
- CentOS7系统如何修改主机名_centos更改主机名称
- 前端工程师需要熟悉的Linux服务器(SSH 终端操作)指令
- Linux开机自启服务完全指南:3步搞定系统服务管理器配置
- 标签列表
-
- idea eval reset (50)
- vue dispatch (70)
- update canceled (42)
- order by asc (53)
- spring gateway (67)
- 简单代码编程 贪吃蛇 (40)
- transforms.resize (33)
- redisson trylock (35)
- 卸载node (35)
- np.reshape (33)
- torch.arange (34)
- npm 源 (35)
- vue3 deep (35)
- win10 ssh (35)
- vue foreach (34)
- idea设置编码为utf8 (35)
- vue 数组添加元素 (34)
- std find (34)
- tablefield注解用途 (35)
- python str转json (34)
- java websocket客户端 (34)
- tensor.view (34)
- java jackson (34)
- vmware17pro最新密钥 (34)
- mysql单表最大数据量 (35)