C# Serilog的使用
Serilog简介
Serilog为文件、控制台和其他地方提供诊断日志记录。它易于设置,有一个干净的API,并且可以在最新的.NET平台之间移植。同时Serilog的也提供了强大的结构化事件数据的能力。
下文设计的示例均为案例一二下的代码修改
Serilog等级
Serilog等级设置如下:
等级 | 说明 |
---|---|
Verbose |
最低级别,很少(如果有的话)为生产应用程序启用 |
Debug |
调试用于内部系统事件,主要用于系统调试下的信息,不建议用于常规记录 |
Information |
信息事件描述了系统中发生的与其职责和功能相对应的事情。一般来说,主要记录系统运行信息 |
Warning |
当服务降级、受到威胁或可能超出其预期参数时,将使用警告级别事件 |
Error |
当功能不可用,期望值被打破时或出现程序bug时,将使用“错误”事件 |
Fatal |
最严重的一级,出现严重影响程序运行时,致命事件需要立即关注 |
Serilog Enricher
Serilog Enricher可以通过各种方式丰富提供更加丰富属性。Serilog同时存在内置Enricher和自定义Enricher
- 部分系统内置Enricher为:
位置 | 项 |
---|---|
Serilog.Enrichers.Environment | WithMachineName() 和 WithEnvironmentUserName() |
Serilog.Enrichers.Process | WithProcessId() |
Serilog.Enrichers.Thread | WithThreadId() |
Serilog.Web.Classic | WithHttpRequestId() 和其他 |
Serilog.Exceptions | WithExceptionDetails() |
Serilog.Enrichers.Demystify | WithDemystifiedStackTraces() |
Serilog.Enrichers.ClientInfo | WithClientIp(), WithCorrelationId() ,WithRequestHeader("header") 和WithRequestHeader("name") |
Serilog.Enrichers.ExcelDna | WithXllPath() 和其他 |
Serilog.Enrichers.Sensitive | WithSensitiveDataMasking() |
Serilog.Enrichers.GlobalLogContext | FromGlobalLogContext() |
第一步,首先安装Nuget包Serilog.Enrichers.Thread
Install-Package Serilog.Enrichers.Thread
第二部,代码中添加对应的内置的Enricher
一下示例Enrich.WithEnvironmentUserName()
将计算机用户打印至日志中
services.AddLogging(logBuilder =>
{
Log.Logger = new LoggerConfiguration().MinimumLevel.Debug()
.Enrich.WithEnvironmentUserName()
.WriteTo.Console(new JsonFormatter())
.WriteTo.File("SerilFileLog.txt", outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}]{Message:lj}{NewLine}{Exception}")
.CreateLogger();
logBuilder.AddSerilog();
});
以上的测试结果为:
- 自定义Enricher
第一步,首先安装Nuget包Serilog
Install-Package Serilog
第二步,自定类实现对应的接口,此处代码演示多新增一个扩展方法
自定义Enricher类
//新增类文件
using Microsoft.AspNetCore.Http;
using Serilog.Configuration;
using Serilog;
using Serilog.Core;
using Serilog.Events;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SerilogTest
{
public class InfoEnricher : ILogEventEnricher
{
public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
{
logEvent.AddPropertyIfAbsent(propertyFactory.CreateProperty("Hello", "Hello World"));
}
}
public static class EnricherExtensions
{
public static LoggerConfiguration WithInfo(this LoggerEnrichmentConfiguration enrich)
{
if (enrich == null)
throw new ArgumentNullException(nameof(enrich));
return enrich.With<InfoEnricher>();
}
}
}
控制台入口类
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Serilog;
using Serilog.Formatting.Json;
using Serilog.Settings.Configuration;
using System.Diagnostics.CodeAnalysis;
using Serilog.Core;
using Serilog.Events;
using Serilog.Enrichers;
namespace SerilogTest
{
internal class Program
{
private static void Main(string[] args)
{
ServiceCollection services = new ServiceCollection();
services.AddLogging(logBuilder =>
{
Log.Logger = new LoggerConfiguration().MinimumLevel.Debug()
.Enrich.WithEnvironmentUserName()
.Enrich.WithInfo()
//使用自定义的Enricher
.WriteTo.Console(new JsonFormatter())
.WriteTo.File("SerilFileLog.txt", outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}]{Message:lj}{NewLine}{Exception}")
.CreateLogger();
logBuilder.AddSerilog();
});
services.AddScoped<Test1>();
using (var sp = services.BuildServiceProvider())
{
var test1 = sp.GetRequiredService<Test1>();
for (int i = 0; i < 1; i++)
{
test1.Test();
}
}
}
}
}
Test1类
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SerilogTest
{
public class Test1
{
private readonly ILogger<Test1> logger;
public Test1(ILogger<Test1> logger)
{
this.logger = logger;
}
public void Test()
{
logger.LogInformation("开始");
logger.LogDebug("开始执行数据库同步");
logger.LogDebug("连接数据库成功");
logger.LogWarning("查找数据库失败,重试第一次");
logger.LogWarning("查找数据库失败,重试第二次");
logger.LogError("查找数据最终失败");
var user = new { Name = "admin", Email = "123@qq.com" };
logger.LogDebug("注册一个用户{@user}", user);
}
}
}
以上代码的测试结果为:
Serilog使用Filter
Filter可以有选择性的筛选出某些数据,可以通过Func委托来过滤数据
- ByIncludingOnly筛选出Key为Hello,值为Hello World的数据
- ByExcluding筛选时去除掉Key为Hello,值为Hello World的数据
控制台入口类
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Serilog;
using Serilog.Formatting.Json;
using Serilog.Settings.Configuration;
using System.Diagnostics.CodeAnalysis;
using Serilog.Core;
using Serilog.Events;
using Serilog.Enrichers;
using Serilog.Filters;
using System.Reflection.Emit;
namespace SerilogTest
{
internal class Program
{
private static void Main(string[] args)
{
ServiceCollection services = new ServiceCollection();
services.AddLogging(logBuilder =>
{
Log.Logger = new LoggerConfiguration().MinimumLevel.Debug()
.Enrich.WithEnvironmentUserName()
.Enrich.WithInfo()
.Filter.ByIncludingOnly(Matching.WithProperty<string>("Hello", p => p.Equals("Hello World")))
//.Filter.ByExcluding(Matching.WithProperty<string>("Hello", p => p.Equals("Hello World")))
.WriteTo.Console(new JsonFormatter())
.WriteTo.File("SerilFileLog.txt", outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}]{Message:lj}{NewLine}{Exception}")
.CreateLogger();
logBuilder.AddSerilog();
});
services.AddScoped<Test1>();
using (var sp = services.BuildServiceProvider())
{
var test1 = sp.GetRequiredService<Test1>();
for (int i = 0; i < 1; i++)
{
test1.Test();
}
}
}
}
}
自定义Enricher类
using Microsoft.AspNetCore.Http;
using Serilog.Configuration;
using Serilog;
using Serilog.Core;
using Serilog.Events;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SerilogTest
{
public class InfoEnricher : ILogEventEnricher
{
public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
{
logEvent.AddPropertyIfAbsent(propertyFactory.CreateProperty("Hello", "Hello World"));
}
}
public static class EnricherExtensions
{
public static LoggerConfiguration WithInfo(this LoggerEnrichmentConfiguration enrich)
{
if (enrich == null)
throw new ArgumentNullException(nameof(enrich));
return enrich.With<InfoEnricher>();
}
}
}
Test1类
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SerilogTest
{
public class Test1
{
private readonly ILogger<Test1> logger;
public Test1(ILogger<Test1> logger)
{
this.logger = logger;
}
public void Test()
{
logger.LogInformation("开始");
logger.LogDebug("开始执行数据库同步");
logger.LogDebug("连接数据库成功");
logger.LogWarning("查找数据库失败,重试第一次");
logger.LogWarning("查找数据库失败,重试第二次");
logger.LogError("查找数据最终失败");
var user = new { Name = "admin", Email = "123@qq.com" };
logger.LogDebug("注册一个用户{@user}", user);
}
}
}
测试结果分别如下:
案例演示一
第一步,首先安装Nuget包Serilog.AspNetCore,该包依赖于Seilog同时还依赖于其他相关的组件
Install-Package Serilog.AspNetCore
第二步,此处我们建立控制台程序用于测试输出
代码方式控制日志输出格式为:
- 设置格式为Json格式
- 打印日志至控制台
- 以"{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj}{NewLine}{Exception}"输出至文件中
- 设置最小输出等级为Debug
控制台入口类
using Microsoft.Extensions.DependencyInjection;
using Serilog;
using Serilog.Formatting.Json;
namespace SerilogTest
{
internal class Program
{
private static void Main(string[] args)
{
ServiceCollection services = new ServiceCollection();
services.AddLogging(logBuilder =>
{
Log.Logger = new LoggerConfiguration().MinimumLevel.Debug()
.Enrich.FromLogContext()
.WriteTo.Console(new JsonFormatter())
.WriteTo.File("SerilFileLog.txt", outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj}{NewLine}{Exception}")
.CreateLogger();
logBuilder.AddSerilog();
});
services.AddScoped<Test1>();
using (var sp = services.BuildServiceProvider())
{
var test1 = sp.GetRequiredService<Test1>();
for (int i = 0; i < 1; i++)
{
test1.Test();
}
}
}
}
}
Test1类
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SerilogTest
{
public class Test1
{
private readonly ILogger<Test1> logger;
public Test1(ILogger<Test1> logger)
{
this.logger = logger;
}
public void Test()
{
logger.LogInformation("开始");
logger.LogDebug("开始执行数据库同步");
logger.LogDebug("连接数据库成功");
logger.LogWarning("查找数据库失败,重试第一次");
logger.LogWarning("查找数据库失败,重试第二次");
logger.LogError("查找数据最终失败");
var user = new { Name = "admin", Email = "123@qq.com" };
//结构化输出类,类可以保存成Json格式
logger.LogDebug("注册一个用户{@user}", user);
}
}
}
测试结果如下:
案例演示二
第一步,首先安装Nuget包Serilog.AspNetCore,该包依赖于Seilog同时还依赖于其他相关的组件
Install-Package Serilog.AspNetCore
Install-Package Microsoft.Extensions.Configuration.Json
Install-Package Serilog.Sinks.Console
Install-Package Serilog.Sinks.File
Install-Package Serilog.Enrichers.Environment
Install-Package Serilog.Enrichers.Thread
第二步,此处我们建立控制台程序用于测试输出
配置文件设置配置项方式控制日志输出格式为:
- 设置格式为Json格式
- 打印日志至控制台
- 以"{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj}{NewLine}{Exception}"输出至文件中
- 设置最小输出等级为Debug
控制台入口类
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Serilog;
using Serilog.Formatting.Json;
using Serilog.Settings.Configuration;
using System.Diagnostics.CodeAnalysis;
using Serilog.Core;
using Serilog.Events;
namespace SerilogTest
{
internal class Program
{
private static void Main(string[] args)
{
ServiceCollection services = new ServiceCollection();
//services.AddLogging(logBuilder =>
//{
// Log.Logger = new LoggerConfiguration().MinimumLevel.Debug()
// .Enrich.FromLogContext()
// .WriteTo.Console(new JsonFormatter())
// .WriteTo.File("SerilFileLog.txt", outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj}{NewLine}{Exception}")
// .CreateLogger();
// logBuilder.AddSerilog();
//});
services.AddLogging(logBuilder =>
{
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(
new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json")
.Build()
)
.CreateLogger();
logBuilder.AddSerilog();
});
services.AddScoped<Test1>();
using (var sp = services.BuildServiceProvider())
{
var test1 = sp.GetRequiredService<Test1>();
for (int i = 0; i < 1; i++)
{
test1.Test();
}
}
}
}
}
Test1类
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SerilogTest
{
public class Test1
{
private readonly ILogger<Test1> logger;
public Test1(ILogger<Test1> logger)
{
this.logger = logger;
}
public void Test()
{
logger.LogInformation("开始");
logger.LogDebug("开始执行数据库同步");
logger.LogDebug("连接数据库成功");
logger.LogWarning("查找数据库失败,重试第一次");
logger.LogWarning("查找数据库失败,重试第二次");
logger.LogError("查找数据最终失败");
var user = new { Name = "admin", Email = "123@qq.com" };
//结构化输出类,类可以保存成Json格式
logger.LogDebug("注册一个用户{@user}", user);
}
}
}
配置项类
//appsettings.json
{
"Serilog": {
"Using": [ "Serilog.Sinks.Console", "Serilog.Sinks.File" ],
"MinimumLevel": "Debug",
"WriteTo": [
{ "Name": "Console" },
{
"Name": "File",
"Args": { "path": "Logs/Serilog.txt" }
}
],
"Enrich": [ "FromLogContext", "WithMachineName", "WithThreadId" ],
"Destructure": [
{
"Name": "ToMaximumDepth",
"Args": { "maximumDestructuringDepth": 4 }
},
{
"Name": "ToMaximumStringLength",
"Args": { "maximumStringLength": 100 }
},
{
"Name": "ToMaximumCollectionCount",
"Args": { "maximumCollectionCount": 10 }
}
],
"Properties": {
"Application": "Sample"
}
}
}
以上测试结果为:
案例演示三
将数据写入到sql server数据库中
第一步,首先安装Nuget包Serilog.AspNetCore,该包依赖于Seilog同时还依赖于其他相关的组件
Install-Package Serilog.AspNetCore
Install-Package Microsoft.Extensions.Configuration.Json
Install-Package Serilog.Sinks.Console
Install-Package Serilog.Sinks.File
Install-Package Serilog.Enrichers.Environment
Install-Package Serilog.Enrichers.Thread
Install-Package Serilog.Sinks.MSSqlServer
控制台入口类
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Serilog;
using Serilog.Formatting.Json;
using Serilog.Settings.Configuration;
using System.Diagnostics.CodeAnalysis;
using Serilog.Core;
using Serilog.Events;
using Serilog.Enrichers;
using Serilog.Filters;
using System.Reflection.Emit;
using Serilog.Sinks.MSSqlServer;
namespace SerilogTest
{
internal class Program
{
private static void Main(string[] args)
{
ServiceCollection services = new ServiceCollection();
//services.AddLogging(logBuilder =>
//{
// Log.Logger = new LoggerConfiguration().MinimumLevel.Debug()
// .Enrich.WithEnvironmentUserName()
// .Enrich.WithInfo()
// .WriteTo.Console(new JsonFormatter())
// .WriteTo.File("SerilFileLog.txt", outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}]{Message:lj}{NewLine}{Exception}")
// .WriteTo.MSSqlServer(connectionString: "Server=localhost;Database=SerilogTest;User Id=sa; Password=123456;", sinkOptions: new MSSqlServerSinkOptions { TableName = "Log" })
// .CreateLogger();
// logBuilder.AddSerilog();
//});
services.AddLogging(logBuilder =>
{
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(
new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json")
.Build()
)
.CreateLogger();
logBuilder.AddSerilog();
});
services.AddScoped<Test1>();
using (var sp = services.BuildServiceProvider())
{
var test1 = sp.GetRequiredService<Test1>();
for (int i = 0; i < 1; i++)
{
test1.Test();
}
}
}
}
}
Test1类
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SerilogTest
{
public class Test1
{
private readonly ILogger<Test1> logger;
public Test1(ILogger<Test1> logger)
{
this.logger = logger;
}
public void Test()
{
logger.LogInformation("开始");
logger.LogDebug("开始执行数据库同步");
logger.LogDebug("连接数据库成功");
logger.LogWarning("查找数据库失败,重试第一次");
logger.LogWarning("查找数据库失败,重试第二次");
logger.LogError("查找数据最终失败");
var user = new { Name = "admin", Email = "123@qq.com" };
//结构化输出类,类可以保存成Json格式
logger.LogDebug("注册一个用户{@user}", user);
}
}
}
配置项类
//appsettings.json
{
"Serilog": {
"Using": [ "Serilog.Sinks.Console", "Serilog.Sinks.File" ],
"MinimumLevel": "Debug",
"WriteTo": [
{ "Name": "Console" },
{
"Name": "File",
"Args": { "path": "Logs/Serilog.txt" }
},
{
"Name": "MSSqlServer",
"Args": {
"connectionString": "Server=localhost;Database=SerilogTest;User Id=sa; Password=123456;",
"tableName": "Log",
"autoCreateSqlTable": true
}
}
],
"Enrich": [ "FromLogContext", "WithMachineName", "WithThreadId" ],
"Destructure": [
{
"Name": "ToMaximumDepth",
"Args": { "maximumDestructuringDepth": 4 }
},
{
"Name": "ToMaximumStringLength",
"Args": { "maximumStringLength": 100 }
},
{
"Name": "ToMaximumCollectionCount",
"Args": { "maximumCollectionCount": 10 }
}
],
"Properties": {
"Application": "Sample"
}
}
}
Serilog自动创建的数据库表格等同如下如下:
CREATE TABLE [Logs] (
[Id] int IDENTITY(1,1) NOT NULL,
[Message] nvarchar(max) NULL,
[MessageTemplate] nvarchar(max) NULL,
[Level] nvarchar(128) NULL,
[TimeStamp] datetime NOT NULL,
[Exception] nvarchar(max) NULL,
[Properties] nvarchar(max) NULL
CONSTRAINT [PK_Logs] PRIMARY KEY CLUSTERED ([Id] ASC)
);
Serilog官方Github wiki Configuration Basics · serilog/serilog Wiki (github.com)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 上周热点回顾(3.3-3.9)
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」