為什么使用Serilog
Serilog 是一個用於.NET應用程序的日志記錄開源庫,配置簡單,接口干凈,並可運行在最新的.NET平台上,與其他日志庫不同, Serilog 是以功能強大的結構化事件數據為基礎構建的, 支持將日志輸出到控制台、文件、數據庫和其它更多的方式,支持參數化日志模板,非常靈活。
之前我們項目使用的是Log4j來記錄用戶日志的,在開發的過程中,慢慢的發現Log4j好像並不能滿足我們的需求,比如結構化,日志分析等,於是決定使用serilog來替換掉Log4j,在使用的過程中發現Serilog還是很強大的。
刪除原有的Log4j
1.卸載log4j包
2.刪除log4j文件夾
3.刪除startup的代碼
4.將log4j相關的代碼刪除
安裝Serilog包
nuget安裝以下幾個包
配置Serilog
編輯Appsetting.json
"Serilog": {
"MinimumLevel": {
"Default": "Debug", //最小日志記錄級別
"Override": { //系統日志最小記錄級別
"Default": "Warning",
"System": "Warning",
"Microsoft": "Warning"
}
},
"WriteTo": [
{ "Name": "Console" }//輸出到控制台
]
},
program.cs將系統的logger替換為serilog
public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .UseServiceProviderFactory(new AutofacServiceProviderFactory()) //<--NOTE THIS .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>() .UseSerilog((context, logger) =>//注冊Serilog { logger.ReadFrom.Configuration(context.Configuration); logger.Enrich.FromLogContext(); }); });
Test控制器注入logger,並修改LogTest方法。
private readonly ILogger<TestController> _logger; public TestController(ILogger<TestController> logger) { _logger = logger; }
/// <summary> /// 測試日志 /// </summary> /// <returns></returns> [HttpGet] public IActionResult LogTest() { //_logger.Error(typeof(TestController), "這是錯誤日志", new Exception("123")); //_logger.Debug(typeof(TestController), "這是bug日志"); //throw new System.IO.IOException(); _logger.LogInformation("info 日志"); _logger.LogDebug("debug 日志"); _logger.LogError(new System.IO.IOException(), "io 錯誤"); return Ok(); }
可以看到日志輸出到了控制台
配置Serilog輸出到文件
appsetting.json增加配置
"WriteTo": [
{ "Name": "Console" }, //輸出到控制台
{
"Name": "Async", //Serilog.Sinks.Async
"Args": {
"configure": [
{
"Name": "File", //輸出文件
"Args": {
"path": "log/log.txt",
"outputTemplate": "{NewLine}Date:{Timestamp:yyyy-MM-dd HH:mm:ss.fff}{NewLine}LogLevel:{Level}{NewLine}Message:{Message}{NewLine}{Exception}",
"rollingInterval": "3" //按天記錄
}
}
]
}
}
]
啟動項目測試
生成了日志文件
輸出到了數據庫
配置Serilog輸出到數據庫
appsetting.json配置
{"Name": "Async", //Serilog.Sinks.Async
"Args": {
"configure": [
{
"Name": "File", //輸出文件
"Args": {
"path": "log/log.txt",
"outputTemplate": "{NewLine}Date:{Timestamp:yyyy-MM-dd HH:mm:ss.fff}{NewLine}LogLevel:{Level}{NewLine}Message:{Message}{NewLine}{Exception}",
"rollingInterval": "3" //按天記錄
}
},
{
"Name": "MSSqlServer", //輸出到sqlserver "Args": { "connectionString": "Server=.;User Id=sa;Password=sa123;Database=ApiLog;MultipleActiveResultSets=true", "schemaName": "dbo", //數據庫所有者,默認dbo "tableName": "Logs", // 記錄日志的表名 "autoCreateSqlTable": true, // 是否自動創建表 "restrictedToMinimumLevel": "Information", // 記錄日志的最小level "batchPostingLimit": 100, //單次批量處理中提交的最大日志數量 "period": "0.00:00:30", //進行批量提交的間隔 "columnOptionsSection": { "disableTriggers": true, "clusteredColumnstoreIndex": false, "primaryKeyColumnName": "Id", "addStandardColumns": [ "LogEvent" ], "removeStandardColumns": [ "MessageTemplate" ], "additionalColumns": [ //自定義列 { "ColumnName": "Ip", "DataType": "varchar", "DataLength": 20 }, { "ColumnName": "UserName", "DataType": "varchar", "DataLength": 30 }, { "ColumnName": "UserId", "DataType": "varchar", "DataLength": 50 }, { "ColumnName": "LogType", "DataType": "tinyint" }, { "ColumnName": "Parameter" }, { "ColumnName": "Result" } ], "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" } } } }
]
}
}
Test控制器修改Aoptest方法,添加以下語句
_logger.LogInformation("ip:{IP},username{UserName},userid:{UserId}","127.0.0.1","admin","1");
啟動項目,測試接口,數據庫已經插入數據。
配置Serilog輸出到Seq
Seq組件,通過網頁UI的形式將日志展現出來,內容更加多樣化,並賦予了更多功能日志搜索。
首先,安裝Seq組件,Seq下載地址:https://getseq.net/Download
本地開發情形下是免費使用的,如果需要在生產環境中使用,需要商業許可(你懂的,money).在目前的版本中,4.2是只能夠在windows下跑,也就是說我們如果是在windows下開發,在測試時可以借助這個方便的查看日志信息,按照給定的安裝步驟完成安裝。
安裝完成之后,瀏覽器輸出localhost:5341,會看到以下頁面
appsetting.json配置輸出到seq
{
"Name": "Seq", //輸出到seq
"Args": {
"serverUrl": "http://192.168.0.89:5341"
}
},
啟動項目,測試接口,可以通過頁面看到數據。
全局使用Serilog記錄日志
在CustomExceptionMiddleware.cs直接這樣
public class CustomExceptionMiddleware { private readonly RequestDelegate _next; private readonly ILogger<CustomExceptionMiddleware> _logger; public CustomExceptionMiddleware(RequestDelegate next, ILogger<CustomExceptionMiddleware> logger) { _next = next; } public async Task Invoke(HttpContext httpContext) { try { await _next(httpContext); } catch (Exception ex) { _logger.LogError(ex.Message, ex); // 日志記錄 await HandleExceptionAsync(httpContext, ex.Message); }
GlobalExceptionsFilter中也一樣
public class GlobalExceptionsFilter : IExceptionFilter { private readonly IHostEnvironment _env; private readonly ILogger<GlobalExceptionsFilter> _logger; public GlobalExceptionsFilter(IHostEnvironment env, ILogger<GlobalExceptionsFilter> logger) { _env = env; _logger = logger; } public void OnException(ExceptionContext context) { var json = new JsonErrorResponse(); json.Message = context.Exception.Message;//錯誤信息 if (_env.IsDevelopment()) { json.DevelopmentMessage = context.Exception.StackTrace;//堆棧信息 } context.Result = new InternalServerErrorObjectResult(json); _logger.LogError(context.Exception, context.Exception.Message); }
如果想在服務層或倉儲層用的話,安裝這個包
然后直接代碼里用就行了