利用C#自帶組件強壯程序日誌

在項目正式上線後,若是出現錯誤,異常,崩潰等狀況html

咱們每每第一想到的事就是查看日誌數據庫

因此日誌對於一個系統的維護是很是重要的app

聲明

正文中的代碼只是一個栗子,一個很是簡單的栗子,只是說明這個框架是怎麼工做的框架

具體實現能夠自由發揮~~~~ide

貫穿全部的日誌系統

日誌系統,每每是貫穿一個程序的全部代碼的;函數

試想一下,若是你的日誌徹底是由第三方組件提供的;測試

那麼就意味着,你的全部項目都必須引用這個dll;ui

也許你會說本身能夠2次封裝,那麼依然須要全部項目都引用你的這個封裝後的log項目spa

另外一方面debug

一些log組件須要實例化後纔可使用,好比log4net,這又意味着你得有一個全局的靜態變量,或者你本身二次封裝

 

但其實微軟已經爲咱們提供了2個十分方便的靜態類,用於日誌的記錄

System.Diagnostics.Trace和System.Diagnostics.Debug

關於這2個類的文檔能夠去看MSDN

System.Diagnostics.Trace

System.Diagnostics.Debug

他的使用真的是很是的方便,以致於你只要使用一次就會愛上他

不用引用任何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);
        }
    }
MyTraceListener
配置文件
<?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就能夠了

說完了...拜拜~~

代碼下載

LogDemo.rar

 


擼主發飆了.......

#13樓   2014-04-02 09:25  永遠的麥子   
兄弟寫得很是好。
不過我有兩個問題:
1,目前是往文本文件寫,若是同時也要往系統事件或數據庫中寫,要怎麼處理?
2,像企業庫這些第三方組件,能夠設置按日期或限定文件大小去循環生成日誌,這又要怎麼處理?
#14樓   2014-04-02 09:26  瀟湘吹雨   
博客君,這個Trace方式,在寫入操做比較頻繁的時候,常常出現不少guid命名的文件,而後寫入的一條內容
#23樓   2014-04-02 10:27  censhao   
不錯,適用簡單的程序。
複雜的程序,好比輕易就能產生幾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系統了啊 ,是否是就想寫數據庫就寫數據庫 想寫文件就寫文件, 寫幹啥就幹啥了啊~~~~~~

兄弟們啊~~~~~~~

相關文章
相關標籤/搜索