Serilog 简介
Serilog 是. net 中的诊断日志库, 可以在所有的. net 平台上面运行. Serilog 支持结构化日志记录, 对复杂, 分布式, 异步应用程序的支持非常出色. Serilog 可以通过插件的方式把日志写入到各种终端, 控制台, 文本, Sqlserver,Elasticsearch,Serilog 支持终端的列表: .
Serilog 日志写入 SqlServer
一, Sink LoggerConfiguration
connectionString 数据库连接字符串
schemaName 数据库所有者, 默认 dbo
tableName 记录日志的表名
autoCreateSqlTable 是否自动创建表, 如果设置为 ture, 则在 Serilog 启动时检测数据库是否有对应的表, 没有则创建
columnOptions 日志表中的列定义
restrictedToMinimumLevel 记录日志的最小 level
batchPostingLimit 单次批量处理中提交的最大日志数量
period 进行批量提交的间隔
formatProvider 提供特定的格式化处理, https://github.com/serilog/serilog/wiki/Formatting-Output#format-providers
Serilog 为我们定义了一套标准列, 默认情况下会生成如下列, 当然我们也可以自定义列
StandardColumn.Id 自增 Id
StandardColumn.Message 日志内容
StandardColumn.MessageTemplate 日志模板
StandardColumn.Level 等级
StandardColumn.TimeStamp 记录时间
StandardColumn.Exception 异常信息
StandardColumn.Properties 日志事件属性值
删除标准列:
columnOptions.Store.Remove(StandardColumn.MessageTemplate);
添加自定义列:
- columnOptions.AdditionalColumns = new Collection<SqlColumn>
- {
- new SqlColumn { DataType = SqlDbType.NVarChar, DataLength = 32, ColumnName = "IP" }
- };
完整 LoggerConfiguration 示例如下:
- var columnOptions = new ColumnOptions();
- columnOptions.Store.Remove(StandardColumn.MessageTemplate);// 删除标准列
- columnOptions.Properties.ExcludeAdditionalProperties = true;// 排除已经自定义列的数据
- columnOptions.AdditionalColumns = new Collection<SqlColumn>// 添加自定义列
- {
- new SqlColumn { DataType = SqlDbType.NVarChar, DataLength = 32, ColumnName = "IP" }
- };
- Log.Logger = new LoggerConfiguration()
- .WriteTo.MSSqlServer(
- connectionString: Configuration["Serilog:ConnectionString"],
- tableName: Configuration["Serilog:TableName"],
- batchPostingLimit: Configuration.GetValue<int>("Serilog:BatchPostingLimit"),// 批量插入数据库条数
- period: TimeSpan.FromSeconds(5),// 执行时间间隔
- restrictedToMinimumLevel: Configuration.GetValue<LogEventLevel>("Serilog:MinimumLevel"),
- columnOptions: columnOptions,
- autoCreateSqlTable: true
- ).CreateLogger();
上面的配置也可以全部从配置文件读取:
- {
- "Serilog": {
- "Using": [ "Serilog.Sinks.MSSqlServer" ],
- "MinimumLevel": "Debug",
- "WriteTo": [
- {
- "Name": "MSSqlServer",
- "Args": {
- "connectionString": "NamedConnectionString",
- "schemaName": "EventLogging",
- "tableName": "Logs",
- "autoCreateSqlTable": true,
- "restrictedToMinimumLevel": "Warning",
- "batchPostingLimit": 100,
- "period": "0.00:00:30",
- "columnOptionsSection": {
- "disableTriggers": true,
- "clusteredColumnstoreIndex": false,
- "primaryKeyColumnName": "Id",
- "addStandardColumns": [ "LogEvent" ],
- "removeStandardColumns": [ "MessageTemplate"],
- "additionalColumns": [
- {
- "ColumnName": "IP",
- "DataType": "varchar",
- "DataLength": 32
- }
- ],
- "id": { "nonClusteredIndex": true },
- "properties": {
- "columnName": "Properties",
- "excludeAdditionalProperties": true,
- "dictionaryElementName": "dict",
- "itemElementName": "item",
- "omitDictionaryContainerElement": false,
- "omitSequenceContainerElement": false,
- "omitStructureContainerElement": false,
- "omitElementIfEmpty": true,
- "propertyElementName": "prop",
- "rootElementName": "root",
- "sequenceElementName": "seq",
- "structureElementName": "struct",
- "usePropertyKeyAsElementName": false
- },
- "timeStamp": {
- "columnName": "Timestamp",
- "convertToUtc": true
- },
- "logEvent": {
- "excludeAdditionalProperties": true,
- "excludeStandardColumns": true
- },
- "message": { "columnName": "message" },
- "exception": { "columnName": "exception" }
- }
- }
- }
- ]
- }
- }
- Log.Logger = new LoggerConfiguration().ReadFrom.Configuration(Configuration["Serilog"]);// 需要引用 Microsoft.Extensions.Configuration
二, Logger 使用
1, 直接使用 Serilog 提供的静态类 Log
Log.Information("message");
2, 使用 serilog-extensions-logging 替换. net core 默认日志 Microsoft.Extensions.Logging, 注入 Serilog
- public static IHostBuilder CreateHostBuilder(string[] args) =>
- Host.CreateDefaultBuilder(args)
- .ConfigurewebHostDefaults(webBuilder =>
- {
- webBuilder.CaptureStartupErrors(true)// 捕捉启动异常
- .UseSetting("detailedErrors", "true")// 指定程序应用程序会显示详细的启动错误信息
- .UseStartup<Startup>()
- .ConfigureLogging(builder =>
- {
- builder.ClearProviders();
- builder.AddSerilog();
- });
- });
- private readonly ILogger logger;
- public TestController(ILogger<TestController> logger)
- {
- this.logger = logger;
- }
- logger.Information("Message")
三, 怎么把数据写入自定义列
Serilog 并没有提供 Log.Debug(Message,IP) 方法, 在我们日常开发中可能会有如下几种需求:
1, 设置全局 Property
例如我需要记录当前程序服务器的 ip, 或者我需要记录当前服务的名称, 需要一个共用的字段. 那么我们可以在 LoggerConfiguration 的时候设置一个全局的 Property, 即在相同的 LoggerConfiguration 下面每条日志都可以共用, 我们可以这样配置
- Log.Logger = new LoggerConfiguration()
- .Enrich.FromLogContext()
- .Enrich.WithProperty("IP", GetIP())
- .WriteTo.MSSqlServer(
- connectionString: Configuration["Serilog:ConnectionString"],
- tableName: Configuration["Serilog:TableName"],
- batchPostingLimit: Configuration.GetValue<int>("Serilog:BatchPostingLimit"),// 批量插入数据库条数
- period: TimeSpan.FromSeconds(5),// 执行时间间隔
- restrictedToMinimumLevel: Configuration.GetValue<LogEventLevel>("Serilog:MinimumLevel"),
- columnOptions: columnOptions,
- autoCreateSqlTable: true
- ).CreateLogger();
2, 设置 ForContext 写入 Property
例如我需要记录当前类, 需要在记录日志的时候设置 ForContext
Log.ForContext("Calss", GetType().FullName).Information("message");
这里只是一个例子, 其实 serilog 已经自动帮我们记录了 Calss 的信息, 在 Properties 中可以找到 SourceContext 节点, 里面就记录了相关的命名空间和类
四, 对日志进行过滤
如果系统日志太多, 我们很难快速找到有用的信息, 所以很多时候我们会对日志进行过滤
1, 通过 MinimumLevel 进行过滤
设置 MinimumLevel 的等级进行过滤, Serilog 中 Level 有 Verbose,Debug,Information,Warning,Error,Fatal 几个等级, Serilog 只记录当前等级及比当前等级高的日志.
2, 通过 Override 进行过滤
原理是 serilog 会记录 SourceContext, 里面包含了命名空间和类的信息, 这里我们把 SourceContext 包含 "Microsoft" 的信息过滤掉, 只记录 Error 及 Error 级别以上的信息, 配置如下:
- Log.Logger = new LoggerConfiguration()
- .Enrich.FromLogContext()
- .Enrich.WithProperty("IP", GetIP())
- .MinimumLevel.Override("Microsoft", LogEventLevel.Error)
- .WriteTo.MSSqlServer(
- connectionString: Configuration["Serilog:ConnectionString"],
- tableName: Configuration["Serilog:TableName"],
- batchPostingLimit: Configuration.GetValue<int>("Serilog:BatchPostingLimit"),// 批量插入数据库条数
- period: TimeSpan.FromSeconds(5),// 执行时间间隔
- restrictedToMinimumLevel: Configuration.GetValue<LogEventLevel>("Serilog:MinimumLevel"),
- columnOptions: columnOptions,
- autoCreateSqlTable: true
- ).CreateLogger();
3, 通过 Filter 进行过滤
通过 Filter 可以过滤 Properties 中的值, 比如一般我们会对数据库的错误比较重视, 希望把数据库错误单独放在一个表中, 这时需要用到 Filter, 我们把 SourceContext 中包含数据访问层命名空间的信息提取出来
- string namespace = "DAL";// 数据访问层命名空间
- Log.Logger = new LoggerConfiguration()
- .Enrich.FromLogContext()
- .Enrich.WithProperty("IP", GetIP())
- .MinimumLevel.Override("Microsoft", LogEventLevel.Error)
- .WriteTo.Logger(lc => lc.Filter.ByIncludingOnly(Matching.WithProperty(namespace))
- .WriteTo.MSSqlServer(
- connectionString: Configuration["Serilog:ConnectionString"],
- tableName: Configuration["Serilog:DBErrorTableName"],
- batchPostingLimit: Configuration.GetValue<int>("Serilog:BatchPostingLimit"),// 批量插入数据库条数
- period: TimeSpan.FromSeconds(5),// 执行时间间隔
- columnOptions: columnOptions,
- autoCreateSqlTable: true))
- .WriteTo.Logger(lc => lc.Filter.ByExcluding(Matching.WithProperty(namespace))
- .WriteTo.MSSqlServer(
- connectionString: Configuration["Serilog:ConnectionString"],
- tableName: Configuration["Serilog:DefaultTableName"],
- batchPostingLimit: Configuration.GetValue<int>("Serilog:BatchPostingLimit"),// 批量插入数据库条数
- period: TimeSpan.FromSeconds(5),// 执行时间间隔
- columnOptions: columnOptions,
- autoCreateSqlTable: true))
- .CreateLogger();
五, Enricher
Enricher 的作用主要是增加记录的信息, 比如 Enrich.WithThreadId(), 可以记录线程信息, Enrich.WithProperty() 可以增加属性信息
自定义 Enricher 可以参数这篇文章: https://www.cnblogs.com/weihanli/p/custom-serilog-enricher-to-record-more-info.html
参考资料
- https://github.com/serilog/serilog
- https://www.cnblogs.com/Leo_wl/p/7643400.html
- https://www.cnblogs.com/Leo_wl/p/10943285.html
来源: https://www.cnblogs.com/fengchao1000/p/11811244.html