.NET Core的日誌[5]:利用TraceSource寫日誌

来源:http://www.cnblogs.com/artech/archive/2016/09/13/logging-for-net-core-05.html
-Advertisement-
Play Games

從微軟推出第一個版本的.NET Framework的時候,就在“System.Diagnostics”命名空間中提供了Debug和Trace兩個類幫助我們完成針對調試和跟蹤信息的日誌記錄。在.NET Framework 2.0中,微軟引入了TraceSource並對跟蹤日誌系統進行了優化,優化後的跟... ...


從微軟推出第一個版本的.NET Framework的時候,就在“System.Diagnostics”命名空間中提供了Debug和Trace兩個類幫助我們完成針對調試和跟蹤信息的日誌記錄。在.NET Framework 2.0中,微軟引入了TraceSource並對跟蹤日誌系統進行了優化,優化後的跟蹤日誌系統在.NET Core中又經過了相應的簡化。.NET Core的日誌模型藉助TraceSourceLoggerProvider實現對TraceSource的整合,在正式介紹這個Logger之前,我們先來認識一下TraceSource跟蹤日誌系統中的三個核心對象。[ 本文已經同步到《ASP.NET Core框架揭秘》之中]

目錄
一、基於TraceSource的追蹤日誌系統
二、TraceSourceLogger
三、TraceSourceLoggerProvider

一、基於TraceSource的追蹤日誌系統

對於這個基於TraceSource的跟蹤日誌系統來說,除了TraceSource之外,它還具有額外連個核心的對象,它們分別是TraceListener和SourceSwitch,三者之間的關係如下圖所示。日誌消息的寫入實現在TraceListener上,我們可以將一組TraceListener註冊到某個TraceSource之上。當我們利用TraceSource記錄某條跟蹤日誌時,日誌消息會分發給註冊的每一個TraceListener並由它們將日誌消息寫到對應的目的地。每個TraceSource都具有一個SourceSwitch,後者起到了日誌過濾的作用。具體來說,SourceSwitch定義了相應的過濾條件來幫助TraceSource決定是否應該將跟蹤日誌分發給TraceListener,如果指定的日誌消息不滿足過濾條件,TraceSource將不會進行任何實質性的日誌記錄工作。

11

如下所示的是TraceSource的定義。每一個TraceSource都具有一個名稱,它一般代表寫入跟蹤日誌的應用程式、服務或者組件的名稱。我們可以調用它的三組Trace方法(TraceData、TraceEvent和TraceInformation)來記錄跟蹤日誌。由於這些方法都標註了一個ConditionaleAttribute特性並將條件編譯符“TRACE”,所以針對這些方法的調用只有在針對Trace模式編譯的應用中才是有效的。

   1: public class TraceSource
   2: {
   3:     public TraceListenerCollection Listeners { get; }
   4:     public string             Name { get; }
   5:     public SourceSwitch         Switch { get; set; }
   6:  
   7:     public TraceSource(string name);
   8:     public TraceSource(string name, SourceLevels defaultLevel);
   9:    
  10:     [Conditional("TRACE")]
  11:     public void TraceData(TraceEventType eventType, int id, object data);
  12:     [Conditional("TRACE")]
  13:     public void TraceData(TraceEventType eventType, int id, params object[] data);
  14:  
  15:     [Conditional("TRACE")]
  16:     public void TraceEvent(TraceEventType eventType, int id);
  17:     [Conditional("TRACE")]
  18:     public void TraceEvent(TraceEventType eventType, int id, string message);
  19:     [Conditional("TRACE")]
  20:      public void TraceEvent(TraceEventType eventType, int id, string format, params object[] args);
  21:  
  22:     [Conditional("TRACE")]
  23:     public void TraceInformation(string message);
  24:     [Conditional("TRACE")]
  25:     public void TraceInformation(string format, params object[] args);  
  26: }

通過TraceData、TraceEvent和TraceInformation這三個方法記錄的跟蹤日誌都具有一個通過枚舉類型TraceEventType表示的事件類型,它相當於前面提到的日誌等級。TraceEventType的這些枚舉項的值越小意味著等級越高,定義日誌等級的LogLevel則於此相反。在調用TraceData和TraceEvent方法時,我們需要顯式地為寫入的跟蹤日誌指定事件類型,而TraceInformation方法則預設使用Information類型。

   1: public enum TraceEventType
   2: {
   3:     Critical         = 1,
   4:     Error            = 2,
   5:     Warning          = 4,
   6:     Information      = 8,
   7:     Verbose          = 16,
   8: }

與TraceEventType枚舉對應的還具有另一個名為SourceLevels的枚舉,除了包含五種具體事件類型之外,還具有額外兩個選項All和Off,該枚舉對象被SourceSwitch用來過濾日誌。在調用構造函數創建TraceSource的時候,我們可以指定一個SourceLevels枚舉值作為預設的等級。如果這個等級未作顯式設置,創建的TraceSource採用的等級為Off,這意味著預設情況下針對追蹤日誌的記錄是禁止的。

   1: [Flags]
   2: public enum SourceLevels
   3: {
   4:     All             = -1,
   5:     Off             = 0,
   6:     Critical        = 1,
   7:     Error           = 3,
   8:     Warning         = 7
   9:     Information     = 15,
  10:     Verbose         = 31
  11: }

我們創建的TraceSource是指定(或者預設設置)的表示日誌等級的SourceLevels枚舉會用來創建一個具有如下定義的SourceSwitch對象,TraceSource的Switch屬性返回的就是這麼一個對象。顧名思義,SourceSwitch是一個開關,它利用ShouldTrace方法決定了針對某種類型的跟蹤日誌的寫入操作是應該開啟還是關閉。如下麵的代碼片段所示,ShouldTrace方法返回的結果是根據通過Level屬性返回的跟蹤日誌等級計算出來的,表示跟蹤日誌等級的SourceLevels枚舉正是最初正是由TraceSource在初始化時提供的。

   1: public class SourceSwitch : Switch
   2: {
   3:     public SourceLevels Level {get;set;}
   4:  
   5:     public SourceSwitch(string name);
   6:     public SourceSwitch(string displayName, string defaultSwitchValue);
   7:  
   8:     public bool ShouldTrace(TraceEventType eventType)
   9:     {
  10:         return ((base.SwitchSetting & eventType) > 0);
  11:     }    
  12: }

TraceSource對象自身並不負責針對跟蹤日誌的寫入,它僅僅將日誌的寫入請求分發給註冊的TraceListener並委托它們來完成寫日誌的功能。這些註冊到TraceSource上的TraceListenter被保存到由它的Listeners屬性返回的集合對象中。所有的TraceListener都拍生於如下這個抽象的TraceListener類型,它定義瞭如下兩組TraceData和TraceEvent方法。當我們調用TraceSource的TraceData、TraceEvent和TraceInformation方法時,如果通過SourceSwitch判斷應該開啟針對當前跟蹤日誌的寫入功能,那麼註冊的TraceListener的TraceData或者TraceEvent方法將會被調用。

   1: public abstract class TraceListener : IDisposable
   2: {
   3:     ...
   4:     public virtual void TraceData(TraceEventCache eventCache, string source, TraceEventType eventType, int id, object data);
   5:     public virtual void TraceData(TraceEventCache eventCache, string source, TraceEventType eventType, int id, params object[] data);
   6:  
   7:     public virtual void TraceEvent(TraceEventCache eventCache, string source, TraceEventType eventType, int id);
   8:     public virtual void TraceEvent(TraceEventCache eventCache, string source, TraceEventType eventType, int id, string message);
   9:     public virtual void TraceEvent(TraceEventCache eventCache, string source, TraceEventType eventType, int id, string format, params object[] args);
  10: }

接下來我們通過一個簡單的控制台應用來演示如何創建一個TraceSource並使用它來記錄追蹤日誌。由於TraceSource定義在“System.Diagnostics.TraceSource”這個NuGet包中,我們需要在project.json文件中需要按照如下的方式添加針對這個NuGet包的依賴。和前面演示的實例一樣,為了提供針對中文編碼的支持,我們不得不添加針對“System.Text.Encoding.CodePages”這個NuGet包的依賴。

   1: {
   2:   ...
   3:   "dependencies": {
   4:     "System.Diagnostics.TraceSource": "4.0.0",    
   5:     "System.Text.Encoding.CodePages": "4.0.1"
   6:   }
   7: }

由於TraceSource總是利用註冊在它上面的TraceListener來完成寫日誌的工作,所以我們按照如下的方式自定義了ConsoleTraceListener。顧名思義,ConsoleTraceListener旨在將分發給它的追蹤日誌輸出到控制臺上。如下麵的代碼片段所示,這個ConsoleTraceListener僅僅重寫了Write和WriteLine方法,它們調用定義在Console類型上的同名方法將格式化好的日誌消息輸出到控制臺上。

   1: public class ConsoleTraceListener : TraceListener
   2: {
   3:     public override void Write(string message) => Console.Write(message);
   4:     public override void WriteLine(string message) => Console.WriteLine(message);
   5: }

我們在作為程式入口的Main方法中創建了一個TraceSource對象。在調用構造函數的時候,除了指定TraceSource的名稱(“Program”)之外,我們還設置了一個預設的追蹤日誌等級(Warning)。接下來我們創建了一個ConsoleTraceListener對象並將其註冊到TraceSource對象上。在此之後,我們調用TraceSource的TraceEvent方法記錄了三條追蹤日誌,它們採用的追蹤事件類型分別是Information、Warining和Error。

   1: public class Program
   2: {
   3:     public static void Main(string[] args)
   4:     {
   5:         //註冊EncodingProvider實現對中文編碼的支持
   6:         Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
   7:  
   8:         TraceSource traceSource = new TraceSource(nameof(Program), SourceLevels.Warning);
   9:         traceSource.Listeners.Add(new ConsoleTraceListener());
  10:  
  11:         int eventId = 3721;
  12:         traceSource.TraceEvent(TraceEventType.Information, eventId, "升級到最新.NET Core版本({0})", "1.0.0");
  13:         traceSource.TraceEvent(TraceEventType.Warning, eventId, "併發量接近上限({0}) ", 200);
  14:         traceSource.TraceEvent(TraceEventType.Error, eventId, "資料庫連接失敗(資料庫:{0},用戶名:{1})", "TestDb", "sa");
  15:     }
  16: }

該程式運行之後,我們利用TraceSource記錄的追蹤日誌將會被註冊的ConsoleTraceListener按照如下圖所示的形式輸出到控制臺上。由於我們在創建TraceSource的時候指定了一個預設的追蹤日誌等級Warning,所以只有不低於這個等級的兩條日誌才會顯示在控制臺上。

12

二、TraceSourceLogger

.NET Core的日誌模型利用一個定義在NuGet包“Microsoft.Extensions.Logging.TraceSource”中的TraceSourceLogger類型實現與TraceSource跟蹤日誌系統的整合。從如下麵的代碼片段我們不難看出,一個TraceSourceLogger對象實際上就是對一個TraceSource對象的封裝,在實現的Log<State>方法中,它會調用TraceSource的TraceEvent方法來完成針對日誌消息的寫入工作。

   1: public class TraceSourceLogger : ILogger
   2: {
	   

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 方法: 調用方法 擴展 非原創,原作忘記地址,我是給自己看的 ...
  • 直接使用yield return關鍵字通過類似返回值的方式靈活地構造迭代器 public class EmployeeCollection :IEnumerable<Employee> { private Employee[] employees; #region IEnumerable<Emplo ...
  • 看的代碼越多,寫的代碼越多,就越是享受這些字元,終於漸漸懂得了那種傳聞中的成就感,特別是自己從看不懂然後一步一步學,一個代碼一個代碼地敲,最後哪怕只是完成了一個小功能,也都是特別自豪的!這種自豪不用告訴別人,自己心裡就是特別滿足! 代碼最美的地方就在於所有的不可能都是有可能的...... 顯示的功能 ...
  • String和string的區別 從位置講: 1.String是.NET Framework裡面的String,小寫的string是C#語言中的string 2.如果把using System;刪掉,沒有大寫的String了,System是.NET Framework類庫中的一個函數名. 從性質講: ...
  • 後臺代碼: ...
  • Web.config配置: 在<system.web>節下: 登錄代碼: /// <summary> /// 登錄 /// </summary> public static bool Login(string userName, string userPwd) { MySqlHelper dbHel ...
  • 一、環境及工具 1、伺服器 VirtualBox5.1.4 安裝 Ubuntu Server 16.04 amd64 MySql Ver 14.14 Distrib 5.6.21 Jexus 5.8.1 nginx 1.10.0 dotnet core 1.0.0-preview2-003121 s ...
  • 隨著大規模的項目越來越多,許多項目都引入了依賴註入框架,其中最流行的有Castle Windsor, Autofac和Unity Container。 微軟在最新版的Asp.Net Core中自帶了依賴註入的功能,有興趣可以 "查看這裡" 。 關於什麼是依賴註入容器網上已經有很多的文章介紹,這裡我將 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...