在一次.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,望技術有成后能回來看見自己的腳步