Serilog简介
Serilog是Asp.Net Core 新兴的日志框架,本文这里简单的介绍一下它的用法以及对他进行简单的封装
官网
Serilog配置
安装基础库
- Install-Package Serilog
- Install-Package Serilog.Sinks.Console
其中包Serilog是Log核心库,Serilog.Sinks.Console是Log的控制台输出库,这个也是日志框架的一贯策略,一个核心库加多个输出库组合使用,这样可以保持良好的扩展性。
简单的示例:
using (var log = new LoggerConfiguration()
.WriteTo.Console()
.CreateLogger())
{
log.Information("Hello, world!");
log.Warning("Goodbye, world.");
log.Error("Goodbye, world.");
}
Serilog介绍
LoggerConfiguration
这里用了一个LoggerConfiguration对象,它主要用于创建和设置Log对象,类似于Nlog里面的LogManager类。这里主要用它两个方法:
- WriteTo:WriteTo属性用来设置日志的输出,Serilog将其称为Sink(水槽),还是比较形象的。
- CreateLogger:用于创建一个ILogger类型的Logger对象.
Serilog封装
public static class SerilogHostingExtensions
{
/// <summary>
/// 加载Serilog配置文件
/// </summary>
/// <returns></returns>
public static IConfiguration AddDefaultConfiguration()
{
var environmentName = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
return new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{environmentName}.json", optional: false, reloadOnChange: true)
.AddEnvironmentVariables()
.Build();
}
/// <summary>
/// 使用Serilog日志记录 以文件的方式记录
/// </summary>
/// <param name="hostBuilder"></param>
/// <returns></returns>
public static IWebHostBuilder UseSerilogDefault(this IWebHostBuilder hostBuilder)
{
var config = AddDefaultConfiguration();
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(config)
.WriteTo.Console()
.CreateLogger();
hostBuilder.UseSerilog();
return hostBuilder;
}
/// <summary>
/// 获取log文件
/// </summary>
/// <param name="config"></param>
/// <param name="defaultValue"></param>
/// <returns></returns>
public static string GetLogFile(this IConfiguration config, string defaultValue)
{
return config.GetValue<string>("LogFile", defaultValue);
}
}
Program.cs
//注入日志
builder.WebHost.UseSerilogDefault();
如何使用
ILogger
ILogger对象用于记录日志,和其他日志框架差不多。Serilog日志级别分为如下5级
- Verbose
- Debug
- Information
- Warning
- Error
- Fatal
大多数的日志也是这样5级,只是有的名称叫的不同(NLog第1级叫Trace,其它的一致),每一级别对应一个写Log的函数:
全局Logger对象
在实际的使用过程中,往往并不是每次使用都去创建一个ILogger,一种方式是通过依赖注入的方式创建一个全局的Logger。不过这种方式需要引入DI框架。在小程序中使用不算方便。
另一种方式是直接使用静态的Log类,它也携带了写入日志的方法,用起来非常方便。
常见存储格式
Serilog的输出对象称之为Sink(水槽),github上提供了大量的第三方的可用sinks,这里简单的列举几个常用的:
- Console 输出到控制台
- Debug 输出到VS的Debug窗口
- File 输出到文件
- MongoDB 输出到MongoDB
- LiteDB 输出到文件数据库LiteDB
- SQLite 输出到文件数据库SQLite
- SignalR 输出为SignalR服务
- HTTP 输出到REST服务
- Loki 输出Loki分布式分布式日志框架
- Elasticsearch 输出到ELK分布式日志框架
输出格式配置
Serilog的日志输出通过LoggerConfiguration类配置,详细的配置参数可以参看官方文档:Configuration Basics。在日常使用中,感觉更多的是直接通过LoggerConfiguration在代码中配置。
输出到文件中
安装扩展
- Install-Package Serilog.Sinks.File
/// <summary>
/// 使用Serilog日志记录 以Loki分布式的方式记录
/// </summary>
/// <param name="hostBuilder"></param>
/// <returns></returns>
public static IWebHostBuilder UseSerilogDefault(this IWebHostBuilder hostBuilder)
{
var config = AddDefaultConfiguration();
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(config)
.WriteTo.Console()
.WriteTo.File(config.GetLogFile("logs/.log"), rollingInterval: RollingInterval.Day)
.CreateLogger();
hostBuilder.UseSerilog();
return hostBuilder;
}
配合Loki使用
安装扩展
- Install-Package Serilog.Sinks.Grafana.Loki
- Install-Package Serilog.Settings.Configuration
/// <summary>
/// 使用Serilog日志记录 以Loki分布式的方式记录
/// </summary>
/// <param name="hostBuilder"></param>
/// <returns></returns>
public static IWebHostBuilder UseSerilogDefault(this IWebHostBuilder hostBuilder)
{
var config = AddDefaultConfiguration();
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(config)
.WriteTo.Console()
.Enrich.FromLogContext()
.WriteTo.GrafanaLoki(
"http://localhost:3100")
.CreateLogger();
hostBuilder.UseSerilog();
return hostBuilder;
}
json配置文件形式
{
"Serilog": {
"Using": [
"Serilog.Sinks.Grafana.Loki"
],
"MinimumLevel": {
"Default": "Debug"
},
"WriteTo": [
{
"Name": "GrafanaLoki",
"Args": {
"uri": "http://localhost:3100",
"labels": [
{
"key": "app",
"value": "web_app"
}
],
"propertiesAsLabels": [
"app"
]
}
}
]
}
}
配合ELK使用
安装扩展
- Install-Package serilog.formatting.elasticsearch
- Install-Package serilog.sinks.elasticsearch
- Install-Package Serilog.Settings.Configuration
/// <summary>
/// 使用Serilog日志记录 以ELK分布式的方式记录
/// </summary>
/// <param name="hostBuilder"></param>
/// <returns></returns>
public static IWebHostBuilder UseSerilogDefault(this IWebHostBuilder hostBuilder)
{
var config = AddDefaultConfiguration();
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(config)
.WriteTo.Console()
.WriteTo.Elasticsearch(new ElasticsearchSinkOptions(new Uri("http://localhost:9200") ){
AutoRegisterTemplate = true,
AutoRegisterTemplateVersion = AutoRegisterTemplateVersion.ESv6
})
.CreateLogger();
hostBuilder.UseSerilog();
return hostBuilder;
}
json配置项
/// <summary>
/// 使用Serilog日志记录 以ELK分布式的方式记录
/// </summary>
/// <param name="hostBuilder"></param>
/// <returns></returns>
public static IWebHostBuilder UseSerilogDefault(this IWebHostBuilder hostBuilder)
{
var config = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json")
.Build();
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(config)
.WriteTo.Console()
.Enrich.FromLogContext()
hostBuilder.UseSerilog();
return hostBuilder;
}
var logger = new LoggerConfiguration()
.ReadFrom.Configuration(configuration)
.CreateLogger();
{
"Serilog": {
"WriteTo": [{
"Name": "Elasticsearch",
"Args": {
"nodeUris": "http://localhost:9200;http://remotehost:9200/",
"indexFormat": "custom-index-{0:yyyy.MM}",
"templateName": "myCustomTemplate",
"typeName": "myCustomLogEventType",
"pipelineName": "myCustomPipelineName",
"batchPostingLimit": 50,
"batchAction": "Create",
"period": 2,
"inlineFields": true,
"restrictedToMinimumLevel": "Warning",
"bufferBaseFilename": "C:/Temp/docker-elk-serilog-web-buffer",
"bufferFileSizeLimitBytes": 5242880,
"bufferLogShippingInterval": 5000,
"bufferRetainedInvalidPayloadsLimitBytes": 5000,
"bufferFileCountLimit": 31,
"connectionGlobalHeaders" :"Authorization=Bearer SOME-TOKEN;OtherHeader=OTHER-HEADER-VALUE",
"connectionTimeout": 5,
"emitEventFailure": "WriteToSelfLog",
"queueSizeLimit": "100000",
"autoRegisterTemplate": true,
"autoRegisterTemplateVersion": "ESv2",
"overwriteTemplate": false,
"registerTemplateFailure": "IndexAnyway",
"deadLetterIndexName": "deadletter-{0:yyyy.MM}",
"numberOfShards": 20,
"numberOfReplicas": 10,
"templateCustomSettings": [{ "index.mapping.total_fields.limit": "10000000" } ],
"formatProvider": "My.Namespace.MyFormatProvider, My.Assembly.Name",
"connection": "My.Namespace.MyConnection, My.Assembly.Name",
"serializer": "My.Namespace.MySerializer, My.Assembly.Name",
"connectionPool": "My.Namespace.MyConnectionPool, My.Assembly.Name",
"customFormatter": "My.Namespace.MyCustomFormatter, My.Assembly.Name",
"customDurableFormatter": "My.Namespace.MyCustomDurableFormatter, My.Assembly.Name",
"failureSink": "My.Namespace.MyFailureSink, My.Assembly.Name"
}
}]
}
}