相信不少coder都有這樣的癖好:「自戀」!!對本身編寫的code老是那麼的自信,自豪,Always believe it to be so perfect!!數據庫
不喜歡作單元測試(總以爲它就那樣了能出什麼錯?),不喜歡作日誌(總以爲他沒有什麼用!),不作日誌也就算了還把異常給「吃」了(只是爲了讓別人看不到那又黃又紅的像坨屎同樣的頁面),最終只能獨自一人默默的抓狂,累的像那什麼同樣,自做孽不可活!!編程
其實......餓......我就是這樣的啦(ˉ▽ˉ;)...數組
爲了讓生活的幸福美滿,爲了工做的輕鬆快樂,我決定虔誠的懺悔,痛定思痛,寫一個簡單日誌!(◎﹏◎)...安全
基於TraceSource的系統日誌編輯器
TraceSource官方給出的描述是這樣的:「提供一組方法和屬性,利用這些方法和屬性,應用程序能夠跟蹤代碼的執行並將跟蹤消息和它們的源關聯起來」。總以爲這描述跟系統日誌掛不上勾額,但事實它是用來作系統日誌的一個不錯的東西;ide
首先爲了迎合當今編程思想,先來建2個接口:單元測試
1.ILogger:用於實現日誌的寫入源測試
/// <summary> /// 系統日誌接口 /// </summary> public interface ILogger { /// <summary> /// 系統崩潰錯誤日誌 /// </summary> /// <param name="message">錯誤信息</param> /// <param name="args">設置格式的對象的數組</param> void Fatal(string message, params object[] args); /// <summary> /// 系統崩潰錯誤日誌 /// </summary> /// <param name="message">錯誤信息</param> /// <param name="exception">異常對象</param> /// <param name="args">設置格式的對象的數組</param> void Fatal(string message, Exception exception, params object[] args); /// <summary> /// 系統消息日誌 /// </summary> /// <param name="message">要記錄的信息</param> /// <param name="args">設置格式的對象的數組</param> void Infomation(string message, params object[] args); /// <summary> /// 系統警告日誌 /// </summary> /// <param name="message">警告信息</param> /// <param name="args">設置格式的對象的數組</param> void Warning(string message, params object[] args); /// <summary> /// 系統錯誤日誌 /// </summary> /// <param name="message">錯誤信息</param> /// <param name="args">設置格式的對象的數組</param> void Error(string message, params object[] args); /// <summary> /// 系統錯誤日誌 /// </summary> /// <param name="message">錯誤信息</param> /// <param name="exception">異常對象</param> /// <param name="args">設置格式的對象的數組</param> void Error(string message, Exception exception, params object[] args); }
2.ILoggerFactory:用於生產指定的日誌寫入源編碼
/// <summary> /// 系統日誌工廠 /// </summary> public interface ILoggerFactory { /// <summary> /// 建立一個系統日誌 /// </summary> ILogger Create(); }
爲了方便編碼和保持日誌的統一性,咱們再建一個日誌上下文spa
/// <summary> /// 系統日誌上下文. /// </summary> public static class LoggerContext { static ILoggerFactory _currentLogFactory = null; /// <summary> /// 設置固然上下文使用的日誌工廠 /// <remarks> /// 該上下文始終使用一個日誌工廠進行建立日誌,建議在系統啓動時進行設置,設置後將沒法再進行設置 /// </remarks> /// </summary> /// <param name="factory">日誌工廠</param> public static void SetCurrent(ILoggerFactory factory) { if (_currentLogFactory != null) throw new ArgumentException("該日誌上下文已經設置使用的日誌工廠,沒法進行再次設置,如需使用其餘日誌工廠,請直接實例日誌工廠進行操做。", "factory"); _currentLogFactory = factory; } /// <summary> /// 建立一個日誌 /// </summary> public static ILogger CreateLog() { if (_currentLogFactory == null) throw new NullReferenceException("該日誌上下文還沒有設置日誌工廠,請使用SetCurrent方法進行設置。"); return _currentLogFactory.Create(); } }
好的,如今咱們進入正題,使用TraceSource進行日誌記錄,不要介意哈,進入正題前總要有些前奏, 目的你懂得o(^▽^)o.....
TraceSource 位於命名空間System.Diagnostics下,該命名空間在System.dll中,因此無需添加引用,比較方便。
下面是基於TraceSource的ILogger實現:
public sealed class TraceSourceLogger :ILogger { private const string EXCEPTION_FORMAT = "{0} 捕獲異常信息:{1}"; TraceSource _source; public TraceSourceLogger() { _source = new TraceSource("Bulrush"); } public void Fatal(string message, params object[] args) { if (String.IsNullOrWhiteSpace(message)) return; string messageToTrace = String.Format(CultureInfo.InvariantCulture, message, args); Trace(TraceEventType.Critical, messageToTrace); } public void Fatal(string message, Exception exception, params object[] args) { if (String.IsNullOrWhiteSpace(message) || exception == null) return; string messageToTrace = String.Format(CultureInfo.InvariantCulture, message, args); string exceptionString = exception.ToString(); Trace(TraceEventType.Critical, String.Format(CultureInfo.InvariantCulture, EXCEPTION_FORMAT, messageToTrace, exceptionString)); } public void Infomation(string message, params object[] args) { if (String.IsNullOrWhiteSpace(message)) return; string messageToTrace = String.Format(CultureInfo.InvariantCulture, message, args); Trace(TraceEventType.Information, messageToTrace); } public void Warning(string message, params object[] args) { if (String.IsNullOrWhiteSpace(message)) return; string messageToTrace = String.Format(CultureInfo.InvariantCulture, message, args); Trace(TraceEventType.Warning, messageToTrace); } public void Error(string message, params object[] args) { if (String.IsNullOrWhiteSpace(message)) return; string messageToTrace = String.Format(CultureInfo.InvariantCulture, message, args); Trace(TraceEventType.Error, messageToTrace); } public void Error(string message, Exception exception, params object[] args) { if (String.IsNullOrWhiteSpace(message) || exception == null) return; string messageToTrace = String.Format(CultureInfo.InvariantCulture, message, args); string exceptionString = exception.ToString(); Trace(TraceEventType.Error, String.Format(CultureInfo.InvariantCulture, EXCEPTION_FORMAT, messageToTrace, exceptionString)); } void Trace(TraceEventType eventType, string message) { if (_source != null) { try { _source.TraceEvent(eventType, (int)eventType, message); } catch (SecurityException) { //這裏處理寫入是出現的安全問題,如文件沒有寫入權限。 } } } }
這個實現比較簡單,可是這裏有一個很好的哦,那是什麼呢?嘻嘻就TraceSource裏的Listeners傾聽器,微軟給咱們提供了幾個經常使用的傾聽器,我以爲基本已經夠用了,
1.DefaultTraceListener:默認使用這個,這個傾聽器會輸出在調試器的輸出窗口。
2.EventLogTraceListener: 這個是操做系統日誌的傾聽器,會把日誌記錄在操做系統的事件裏,我仍是比較喜歡這個,畢竟比較完善,安全性也比較好。
3.TextWriterTraceListener:這個是文本編輯器的傾聽器,簡單點就是以文件流的形式進行記錄,固然了文件路徑是本身定義的,這個也比較經常使用。
4.XmlWriterTraceListener:這個Xml文件的傾聽器,用法和TextWriterTraceListener差很少,只是使用Xml流格式進行記錄。
等等,固然還有幾個傾聽器,這裏就不一一列出了,有興趣的能夠查看MSDN的System.Diagnostics。
若是你想拓展也能夠,如記錄在數據庫,或者使用Log4net等等,只要繼承TraceListener基類進行重寫就能夠了。
下面是一個最簡單的自定義傾聽器:
public class CustomeTraceListener : TraceListener { public override void Write(string message) { File.AppendAllText(@"d:\log.txt", message); } public override void WriteLine(string message) { File.AppendAllText(@"d:\log.txt", message+ Environment.NewLine); } }
下面咱們在寫一個TraceSourceLogger工廠就能夠了,代碼以下:
public class TraceSourceLoggerFactory : ILoggerFactory { public ILogger Create() { var logger = new TraceSourceLogger(); return logger; } }
OK,代碼已經寫好了,那又的同窗就要問了傾聽器在哪裏設置呢?
這個問題很簡單,固然是在配置文件裏配置了;
<configuration> <system.diagnostics> <sources> <source name="Bulrush" switchName="SourceSwitch" switchType="System.Diagnostics.SourceSwitch"> <listeners> <clear/> <add name="eventLog"></add> </listeners> </source> </sources> <switches> <!--這裏設置TraceSource的寫入開關,默認爲Off關閉,不進行寫入,具體值能夠查看SourceLevels枚舉--> <add name="SourceSwitch" value="All"/> </switches> <sharedListeners> <!-- 這裏使用操做系統的事件傾聽器,initializeData屬性是事件源,false爲默認。 不一樣的傾聽器initalizeData有不一樣的意義,如TextWriterTraceListnener傾聽器,能夠設置爲「d:\log.txt」,意思就是保存的路徑。 --> <add name="eventLog" type="System.Diagnostics.EventLogTraceListener" initializeData="false"/> </sharedListeners> </system.diagnostics> </configuration>
到這裏就結束了,下面作個簡單的測試,是使用EventLogTraceListener傾聽器:
[ClassInitialize()] public static void ClassInitialze(TestContext context) { LoggerContext.SetCurrent(new TraceSourceLoggerFactory()); } [TestMethod] public void TestTraceSourceLogger() { //LoggerContext.CreateLog().Error("錯誤日誌"); var logger = LoggerContext.CreateLog(); try { logger.Error("錯誤日誌"); logger.Fatal("系統崩潰日誌"); logger.Infomation("普通消息日誌"); logger.Warning("非關鍵性,警告日誌"); } catch { Assert.Fail(); } }
結果爲:
太晚了,該睡覺了哦!!