# 1. 目錄 - [1. 目錄](#1-目錄) - [2. 前言](#2-前言) - [2.1. 日誌控制項的選擇](#21-日誌控制項的選擇) - [3. 日誌配置](#3-日誌配置) - [3.1. 控制台列印](#31-控制台列印) - [3.2. 文件列印](#32-文件列印) - [4. 結 ...
1. 目錄
2. 前言
定時任務中比較重要的一個環節就是日誌記錄,有了日誌可以記錄系統的操作過程,也可以在系統異常時方便排查錯誤原因。
比如定時任務經常要做的一個事情,同步其它異構系統數據到本系統。大多情況下的操作過程時,定時請求對方介面返回JSON格式數據,我方把接收到的數據再轉換為C#對象進行業務處理後保存至資料庫。如果在這個過程中發生系統異常,沒有日誌記錄很有可能連復現BUG都很難做到。
所以在這個過程中,比較正確的日誌記錄方式是:
- 介面請求,如有異常記錄日誌。
- 記錄介面返回值。
- JSON數據轉換為C#對象,如有異常記錄日誌。
- 其它
2.1. 日誌控制項的選擇
之前所有項目用的基本都是老牌Log4net,而這次重構的一大主題是學習新東西嘛,所以我選擇比較年輕一點的Serilog。
為什麼選擇Serilog? 嗯。。。。隨便選的,其實用NLog也不是不行。
3. 日誌配置
在Web項目下創建Extensions文件夾並添加SerilogSetup.cs文件。
添加如下NuGet包
- Serilog 3.0.1 基礎包
- Serilog.Extensions.Hosting 7.0.0 ConfigureHostBuilder的擴展包
- Serilog.Enrichers.Thread 3.1.0 用於獲取線程信息
- Serilog.Sinks.Async 1.5.0 用於非同步列印
- Serilog.Sinks.Console 4.1.0 列印日誌到控制台
- Serilog.Sinks.File 5.0.0 列印日誌到文件
添加全局靜態變數,用於設置列印模板,至於寫法。官網是最好的老師:https://github.com/serilog/serilog/wiki/Configuration-Basics#output-templates
private static readonly string logTemplate = "{NewLine}時聞:{Timestamp:yyyy-MM-dd HH:mm:ss.fff}{NewLine}日誌等級:{Level}{NewLine}線程ID:{ThreadId} 線程名:{ThreadName}{NewLine}所在類:{SourceContext}{NewLine}日誌信息:{Message}{NewLine}{Exception}";
3.1. 控制台列印
接著添加靜態方法AddSerilog
public static void AddSerilog(ConfigureHostBuilder builder)
{
// 列印到控制台
// 生產環境中可以不向控制台列印
builder.UseSerilog((context, logger) =>
{
// 添加此句後可以在“執行上下文”中動態添加和刪除屬性
logger.Enrich.FromLogContext();
logger.MinimumLevel.Information();
logger.Enrich.WithThreadId();
logger.Enrich.WithThreadName();
logger.WriteTo.Logger(lg => lg.WriteTo.Async(a =>
a.Console(outputTemplate: logTemplate)));
});
}
3.2. 文件列印
在AddSerilog方法中添加如下內容
// 列印到文件
builder.UseSerilog((context, logger) =>
{
logger.Enrich.FromLogContext();
logger.Enrich.WithThreadId();
logger.Enrich.WithThreadName();
logger.WriteTo.Logger(lg => lg.Filter.ByIncludingOnly(p => p.Level == LogEventLevel.Debug).WriteTo.Async(a => a.File(logDebug, rollingInterval: RollingInterval.Hour, outputTemplate: logTemplate)));
logger.WriteTo.Logger(lg => lg.Filter.ByIncludingOnly(p => p.Level == LogEventLevel.Information).WriteTo.Async(a => a.File(logInfo, rollingInterval: RollingInterval.Hour, outputTemplate: logTemplate)));
logger.WriteTo.Logger(lg => lg.Filter.ByIncludingOnly(p => p.Level == LogEventLevel.Warning).WriteTo.Async(a => a.File(logWarn, rollingInterval: RollingInterval.Hour, outputTemplate: logTemplate)));
logger.WriteTo.Logger(lg => lg.Filter.ByIncludingOnly(p => p.Level == LogEventLevel.Error).WriteTo.Async(a => a.File(logError, rollingInterval: RollingInterval.Hour, outputTemplate: logTemplate)));
logger.WriteTo.Logger(lg => lg.Filter.ByIncludingOnly(p => p.Level == LogEventLevel.Fatal).WriteTo.Async(a => a.File(logFatal, rollingInterval: RollingInterval.Hour, outputTemplate: logTemplate)));
});
這裡要註意的是,也可以寫在一個方法內,我這樣做的目的是為了可以一目瞭然的區分開不同日誌的配置。
最後在Program.cs 中註冊Serilog相關配置。
SerilogSetup.AddSerilog(builder.Host);
接下來就可以找個地方做列印測試了,比如在HomeController的Index的方法中加放入
_logger.LogInformation("控制台列印");
4. 結語
目前階段只是做了控制台和文件列印,以後也許會接入資料庫列印。
因為後期想在Web頁面查看定時任務的執行狀況等等。
本文原創自博客園,歡迎關註我的博客HOYU_Z https://www.cnblogs.com/hoyu/