在項目正式上線後,如果出現錯誤,異常,崩潰等情況
我們往往第一想到的事就是查看日誌
所以日誌對於一個系統的維護是非常重要的
聲明
正文中的代碼只是一個栗子,一個非常簡單的栗子,只是說明這個框架是怎麼工作的
具體實現可以自由發揮~~~~
貫穿所有的日誌系統
日誌系統,往往是貫穿一個程序的所有代碼的;
試想一下,如果你的日誌完全是由第三方組件提供的;
那麼就意味着,你的所有項目都必須引用這個dll;
也許你會說自己可以2次封裝,那麼依然需要所有項目都引用你的這個封裝後的log項目
另一方面
一些log組件需要實例化後纔可以使用,比如log4net,這又意味着你得有一個全局的靜態變量,或者你自己二次封裝
但其實微軟已經爲我們提供了2個十分方便的靜態類,用於日誌的記錄
System.Diagnostics.Trace和System.Diagnostics.Debug
關於這2個類的文檔可以去看MSDN
他的使用真的是非常的方便,以至於你只要使用一次就會愛上他
不用引用任何dll,因爲他是微軟自家的東西,就在System.dll中
調用他的方法也很簡單
using System.Diagnostics; ... ... Trace.TraceError("這是一個Error級別的日誌"); Trace.TraceWarning("這是一個Warning級別的日誌"); Trace.TraceInformation("這是一個Info級別的日誌"); Trace.WriteLine("這是一個普通日誌"); Trace.Flush();//立即輸出 ... ...
當然方法不止只有4個,更多的可以參考MSDN
Trace,Debug的調用方式完全相同,不同的地方在於
Debug的所有方法都有
[Conditional("DEBUG")]
表明了,在Release模式下(沒有定義DEBUG常量時),該方法不會被編譯的(不是不執行,而是根本不會編譯到程序中去)
也就是說 Debug.XXX() 方法僅在Debug模式下運行,這個又可以爲我們省下很多事
重寫日誌實現
Trace和Debug中的方法的默認行爲是輸出到控制檯Console,和Console.Write是一樣的
但是我們通過改變他的監聽器TraceListener,來實現更多的操作
必須實現的方法有
void Write(string message); void WriteLine(string message);
不過也可以主動重寫其他方法
隨便寫一個MyTraceListener
class MyTraceListener : TraceListener { public override void Write(string message) { File.AppendAllText("d:\\1.log",message); } public override void WriteLine(string message) { File.AppendAllText("d:\\1.log", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ") + message + Environment.NewLine); } }
現在程序入口中初始化監聽器Trace.Listeners
PS下:Trace和Debug的監聽器的共用的
static void Main(string[] args) { Trace.Listeners.Clear(); //清除系統監聽器 (就是輸出到Console的那個) Trace.Listeners.Add(new MyTraceListener()); //添加MyTraceListener實例 }
在隨便來個方法測試下
private static void Test() { try { int i = 0; Console.WriteLine(5 / i); //出現除0異常 } catch (Exception ex) { Trace.TraceError("出現異常:" + ex.Message);//記錄日誌 } }
由於大部分方法都是可重寫的,所以其實最終輸出什麼都是可以靈活處理的
例如這樣
public override void Write(object o, string category) { string msg = ""; if (string.IsNullOrWhiteSpace(category) == false) //category參數不爲空 { msg = category + " : "; } if (o is Exception) //如果參數o是異常類,輸出異常消息+堆棧,否則輸出o.ToString() { var ex = (Exception)o; msg += ex.Message + Environment.NewLine; msg += ex.StackTrace; } else if(o != null) { msg = o.ToString(); } WriteLine(msg); }
private static void Test() { try { int i = 0; Console.WriteLine(5 / i); //出現除0異常 } catch (Exception ex) { Trace.Write(ex, "計算員工工資出現異常"); } }
其他的就自己舉一反三了
通過配置文件初始化監聽器
通過配置文件初始化監聽器比直接寫代碼稍稍複雜一點,但是也更方便,我們可以快速的,不重新編譯系統,即可進行對日誌監聽器進行設定
特別是在Web項目中,這將變得更加方便
我把剛纔的MyTraceListener獨立成一個項目,編譯爲dll
並且爲他增加一個構造函數和FilePath屬性用於設置將log文件的位置
public class MyTraceListener : TraceListener { public string FilePath { get; private set; } public MyTraceListener(string filepath) { FilePath = filepath; } public override void Write(string message) { File.AppendAllText(FilePath, message); } public override void WriteLine(string message) { File.AppendAllText(FilePath, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ") + message + Environment.NewLine); } public override void Write(object o, string category) { string msg = ""; if (string.IsNullOrWhiteSpace(category) == false) //category參數不爲空 { msg = category + " : "; } if (o is Exception) //如果參數o是異常類,輸出異常消息+堆棧,否則輸出o.ToString() { var ex = (Exception)o; msg += ex.Message + Environment.NewLine; msg += ex.StackTrace; } else if (o != null) { msg = o.ToString(); } WriteLine(msg); } }
<?xml version="1.0" encoding="utf-8" ?> <configuration> <system.diagnostics> <trace autoflush="false" indentsize="4"> <listeners> <clear /><!--清除默認監聽器--> <!--添加自定義監聽器 initializeData 就是初始化參數--> <add name="MyTraceListener" type="MyLog.MyTraceListener, MyLog, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" initializeData="d:\1.log" /> </listeners> </trace> <switches> <!--這裏可以設定監聽級別,可以設置Error,Warning,Info或者留空--> <add name="MyTraceListener" value="Error" /> </switches> </system.diagnostics> </configuration>
其中type參數可以這樣獲得
typeof(MyLog.MyTraceListener).AssemblyQualifiedName
Version,Culture,PublicKeyToken 也可以忽略
測試一下
沒有任何問題
而且如果你用了log4net等第三方組件的話,只需要在實現TraceListener的項目中引用log4net就可以了
說完了...拜拜~~
代碼下載
擼主發飆了.......
不錯,適用簡單的程序。
複雜的程序,比如輕易就能產生幾G日誌文件的程序裏還是log4net好用。
兄弟們啊,你們真的是來看文章的嗎? 不是我的對手派來玩我的吧...............咳咳....雞凍了.....
好吧,怪我沒說清楚,我再集中這些問題,用一個栗子簡單回答一下
public class MyTraceListener : TraceListener { log4net _log = new log4net(); public MyTraceListener(string filepath) { _log = new log4net(); _log.FilePath = filepath; } public override void Write(string message) { _log.Info(message); } public override void WriteLine(string message) { _log.Info(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ") + message + Environment.NewLine); } }
這樣是不是就可以用log4net了啊,是不是就可以用其他log系統了啊 ,是不是就想寫數據庫就寫數據庫 想寫文件就寫文件, 寫幹啥就幹啥了啊~~~~~~
兄弟們啊~~~~~~~
http://www.cnblogs.com/blqw/p/3639360.html
不過我有兩個問題:
1,目前是往文本文件寫,如果同時也要往系統事件或數據庫中寫,要怎麼處理?
2,像企業庫這些第三方組件,可以設置按日期或限定文件大小去循環生成日誌,這又要怎麼處理?