1. 程式人生 > >Asp.Net Core中利用Seq組件展示結構化日誌功能

Asp.Net Core中利用Seq組件展示結構化日誌功能

eve 發布 哪裏 HA 快速 inf ron void 級別

在一次.Net Core小項目的開發中,掌握的不夠深入,對日誌記錄並沒有好好利用,以至於一出現異常問題,都得跑動服務器上查看,那時一度懷疑自己肯定沒學好,不然這一塊日誌不可能需要自己扒服務器日誌來查看,果然,很多東西沒掌握,至此,花點時間看了下日誌的相關操作。利用日誌服務來查看日誌數據。

本文地址:https://www.cnblogs.com/CKExp/p/9246788.html

本文Demo的地址:https://gitee.com/530521314/LogPanel.git

一、日誌記錄的原則

  日誌是為了方便我們觀察應用程序是否正常運行,也是當運行不正常是,能夠快速找到出現問題,定位問題的方式。

  有幾條日誌記錄原則是我們大多都得遵循的:

  1、日誌記錄清晰,內容得讓我們能夠知道應用程序運行正常或運行不正常下能夠有關鍵信息指明哪裏出問題了。

  2、不要過度記錄,一些場景下我們需要預判是否需要記錄日誌信息,我們能夠控制日誌記錄的數量,同樣,日誌內容,要精簡記錄,無關緊要的文字,廢話等無需加入。

  3、控制日誌記錄級別,或許在一個日誌級別下記錄了很多信息,可是其中的部分信息才是最為重要的,當調高一個記錄級別,這部分最為重要的信息就展示出來了,那就直接調高級別吧。

  4、隱私保護,日誌雖然是讓開發運維人員看到,可是我們也不能所有信息都記錄下來,用戶的隱私信息我們得保護好。

二、內置日誌組件

  Asp.Net Core中內置了日誌組件,功能也很強大,首先來個簡單示例:

  直接使用內置日誌功能,無需在startup中加入另外的代碼。

 1    private readonly ILogger<HomeController> _logger;
 2 
 3     public HomeController(ILogger<HomeController> logger)
 4     {
 5         _logger = logger;
 6     }
 7 
 8     public IActionResult Index()
 9     {
10 Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); 11 _logger.LogDebug($"開始監控整個網站的日誌信息_{DateTime.Now}"); 12 //_logger.LogError($"開始監控整個網站的日誌信息Error_{DateTime.Now}"); 13 return View(); 14 }

  在調試框下看到輸出的日誌信息。

  技術分享圖片

  開始控制日誌記錄級別:

  在StartUp下,對內置日誌組件做一些處理,在配置文件中將日誌記錄的級別提高到Information級別:

 1     public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
 2     {
   3         //默認日誌功能
 4         loggerFactory.AddConsole(Configuration.GetSection("Logging"));
 5         loggerFactory.AddDebug();
 6         //loggerFactory.AddSerilog();
 7 
 8         if (env.IsDevelopment())
 9         {
10             app.UseBrowserLink();
11             app.UseDeveloperExceptionPage();//更多錯誤信息的開發者異常詳情頁
12         }
13         else
14         {
15             app.UseExceptionHandler("/Home/Error");
16         }
17 
18         app.UseStaticFiles();
19 
20         app.UseMvc(routes =>
21         {
22             routes.MapRoute(
23                 name: "default",
24                 template: "{controller=Home}/{action=Index}/{id?}");
25         });
26     }

  appsetting.json文件中,將LogLevel的默認級別設為Information,這樣一來在之前的示例中_logger.LogDebug將失去作用。

 1 {
 2   "Logging": {
 3     "IncludeScopes": false,
 4     "LogLevel": {
 5       "Default": "Information",
 6       "System": "Error",
 7       "Microsoft": "Error"
 8     }
 9   }
10 }

  對於異常來講,出現異常,日誌肯定得記錄下來,不然出現異常,直接拋出,那還要日誌有什麽用呢。

 1     public IActionResult About()
 2     {
 3         try
 4         {
 5             _logger.LogInformation($"業務邏輯執行前,運行正常");
 6             //執行其它業務邏輯
 7             int textInt = 5;
 8             int result = textInt / 0;
 9             //執行其它業務邏輯
10             _logger.LogInformation($"業務邏輯執行後,運行正常");
11         }
12         catch (Exception ex)
13         {
14             _logger.LogError($"出現異常,異常信息{ex.Message}");
15             throw;
16         }
17 
18         return View();
19     }

  異常信息加載出來。

  技術分享圖片

  出現異常,攔截異常,記錄日誌信息,不單單在這裏,在Filter或是幾個中間件中,都能夠記錄下來,此處不在多討論。

三、第三方日誌組件

  盡管微軟已經內置了日誌記錄組件,但是一些第三方組件或許是我們中意的,在性能上、記錄方式上、操作上等等,如Log4Net、Logger、NLog和Serilog 等。結構化的日誌使得我們閱讀日誌也更加輕松點。

  在此,我利用Serilog組件來替換內置的日誌組件,添加相應的依賴包(Serilog.Extensions.Logging和Serilog.Sinks.Literate)。

  然後來更新Startup類,令Serilog組件開始發揮它的作用。

  盡管可以在Program中加入Serilog組件,在這裏,我將只在StartUp類中更改代碼,為了代碼統一存放,對於組件加入有三種方式:

  方式一在StartUp初始化完畢加入進來,利用Log.Logger的全局性,在整個應用程序中發揮作用,而不需要在各處聲明註入。

  其中的 .WriteTo.Seq("http://localhost:5341")是為了後面加入Seq組件而提前寫入的,可以忽略。

 1     public Startup(IConfiguration configuration)
 2     {
 3         Configuration = configuration;
 4         //方式一:配置Seq服務器的地址(5341端口為默認地址)
 5         Log.Logger = new LoggerConfiguration()
 6             .MinimumLevel.Debug()
 7             .MinimumLevel.Override("LoggingService", Serilog.Events.LogEventLevel.Debug)
 8             .Enrich.FromLogContext()
 9             .WriteTo.Seq("http://localhost:5341")
10             .WriteTo.LiterateConsole()
11             .CreateLogger();
12     }

  在應用程序中的使用方式是直接使用Log.Logger寫入即可,如在HomeController的Contact方法中,利用且只能利用這種方式寫入,當想用最開始那種方式註入時,在LoggerFactory中並沒有SerilogProvider,因為我們並沒有把Serilog加入到LoggerFactory中,這也使得Serilog和內置日誌出現共存的局面,並可以通過兩種方式使用日誌功能。

1     public IActionResult Contact()
2     {
3         Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
4         Log.Debug("Log.Debug:Serilog Start Send Message");
5         Log.Information("Log.Information:Serilog Start send Message");
6         Log.Logger.Debug("Log.Logger:Serilog Start Send Message");
7         Log.Logger.Information("Log.Logger.Information:Serilog Start Send Message");
8         return View();
9     }

  利用這種方式下的日誌輸出。  

  技術分享圖片

   方式二:在ConfigureServices中將Serilog加入到LoggerFactory中,通過統一的擴展方式加入進來,利用Action委托指定Serilog組件,其中允許我們對Serilog進行相關設置。

 1     public void ConfigureServices(IServiceCollection services)
 2     {
 3         //方式二
 4         var serilog = new LoggerConfiguration()
 5                 .MinimumLevel.Information()
 6                 .MinimumLevel.Override("LoggingService", Serilog.Events.LogEventLevel.Debug)
 7                 .Enrich.FromLogContext()
 8                 .WriteTo.Seq("http://localhost:5341")
 9                 .WriteTo.LiterateConsole();
10 
11         services.AddLogging(loggerBuilder =>
12         {
13             loggerBuilder.AddSerilog(serilog.CreateLogger());
14         });
15         services.AddMvc();
16     }

  這種方式下,我們需要將Logger通過依賴註入的形式加入進來,先來看下是否加入到了LoggerFactory中

  技術分享圖片

  加入進來了,並完成了日誌的輸出。

  技術分享圖片

  方式三:和方式二一樣都是加入到LoggerFactory中,但是直接利用的是Serilog提供的擴展方法AddSerilog加入進來。

 1     public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
 2     {
 3         //默認日誌功能
 4         //loggerFactory.AddConsole(Configuration.GetSection("Logging"));
 5         //loggerFactory.AddDebug();
 6 
 7         #region Serilog
 8         //方式三
 9         //默認配置
10         //loggerFactory.AddSerilog();
11 
12         //配置Seq服務器的地址(5341端口為默認地址)
13         //var serilog = new LoggerConfiguration()
14         //    .MinimumLevel.Information()
15         //    .MinimumLevel.Override("LoggingService", Serilog.Events.LogEventLevel.Debug)
16         //    .Enrich.FromLogContext()
17         //    .WriteTo.Seq("http://localhost:5341")
18         //    .WriteTo.LiterateConsole();
19         //loggerFactory.AddSerilog(serilog.CreateLogger());
20         #endregion
21 
22         if (env.IsDevelopment())
23         {
24             app.UseBrowserLink();
25             app.UseDeveloperExceptionPage();//更多錯誤信息的開發者異常詳情頁
26         }
27         else
28         {
29             app.UseExceptionHandler("/Home/Error");
30         }
31 
32         app.UseStaticFiles();
33 
34         app.UseMvc(routes =>
35         {
36             routes.MapRoute(
37                 name: "default",
38                 template: "{controller=Home}/{action=Index}/{id?}");
39         });
40     }

  Serilog組件同源加入進來了,輸出結果就不展示了和方式二一樣的。

  技術分享圖片

  具體Serilog的非常優秀的功能就不介紹了,請看Serilog的官方介紹 https://github.com/serilog

四、Seq組件

  到了本文的主題——Seq組件,通過網頁UI的形式將日誌展現出來,內容更加多樣化,並賦予了更多功能日誌搜索。

  首先,安裝Seq組件,Seq下載地址:https://getseq.net/Download

  本地開發情形下是免費使用的,如果需要在生產環境中使用,需要商業許可(你懂的,money).在目前的版本中,4.2是只能夠在windows下跑,也就是說我們如果是在windows下開發,在測試時可以借助這個方便的查看日誌信息,按照給定的安裝步驟完成安裝。

  在應用程序中,我們通過Nuget管理Serilog.Sinks.Seq包,該組件隸屬於Serilog旗下。Seq默認的端口是利用5341端口,如果我們想要使用其它端口,我們可以更改在應用程序中的地址

  以上一節的方式三為例,在其中加入一行.WriteTo.Seq(“http://localhost:5341”)便可指定Seq服務器地址。

1     var serilog = new LoggerConfiguration()
2         .MinimumLevel.Information()
3         .MinimumLevel.Override("LoggingService", Serilog.Events.LogEventLevel.Debug)
4         .Enrich.FromLogContext()
5         .WriteTo.Seq("http://localhost:5341")
6         .WriteTo.LiterateConsole();
7     loggerFactory.AddSerilog(serilog.CreateLogger());

  在本地windows運行起來看下,啟動Seq服務器,當然,你這裏或許需要配置一些賬號密碼之類的,都是小問題。

  技術分享圖片

  啟動應用程序,並進入那些寫了日誌的方法中,日誌信息已經進來了,我們可以查看這些日誌信息,並通過日誌搜索功能搜索。

  技術分享圖片

  技術分享圖片

  在這裏要說明一下,同時也在Seq組件的網站中也寫明了。使用這些方式都可以直接使用Seq組件,第三方組件也不是必須的,直接利用Asp.Net Core的內置日誌組件一樣可以使用Seq組件。

  技術分享圖片   

  可是,Linux下可以嗎? 假如我的開發環境在Linux下豈不是不行。現在有一個預覽版5.0的,在Docker Hub中有Seq的鏡像,雖然是預覽版,可是我還是想試試。

  Docker Hub中Seq鏡像地址:https://docs.getseq.net/v5.0/docs/docker

  現在,開始Linux中弄起來。

  首先完成鏡像的爬取,之後會自動啟動該鏡像內部的服務。我們直接輸入地址訪問即可。默認地址ip:5341端口

docker run -e ACCEPT_EULA=Y -p 5341:80 datalust/seq:latest

  頁面有了,Linux下看來也是可以的了,把應用程序通過Jenkins上都發布成功了,可是訪問出現問題,Docker外部端口無法映射到內部端口,糟心,可是應該不是大問題,就此也就不弄日誌信息的展示了。

  技術分享圖片

  至此,日誌相關的一系列知識簡單帶過,關鍵是Seq那個可視化日誌界面,很nice。

  本文地址:https://www.cnblogs.com/CKExp/p/9246788.html

  本文Demo的地址:https://gitee.com/530521314/LogPanel.git

2018-6-30,望技術有成後能回來看見自己的腳步

Asp.Net Core中利用Seq組件展示結構化日誌功能