Trace、Debug和TraceSource的使用以及日誌設計

http://www.cnblogs.com/luminji/archive/2010/10/26/1861316.html

C#筆記30:Trace、Debug和TraceSource的使用以及日誌設計

本章概要:

1:Trace 和 Debug區別

2:什麼是Listeners

3:跟蹤開關

     3.1:使用BooleanSwitch開關

     3.2:使用TraceSwitch開關

4:使用TraceSource代替Trace和

5:設計一個日誌系統

6:關於EventLog

 

      .NET Framework 命名空間 System.Diagnostics 包含用於跟蹤執行流程的 TraceDebugTraceSource 類,以及用於分析代碼的 ProcessEventLogPerformanceCounter 類。

      跟蹤是一種在應用程序運行時監視其執行情況的方式。當開發 .NET Framework 應用程序時,可以在其中添加跟蹤和調試檢測功能,並且在開發應用程序時和部署應用程序後,都可以使用該檢測功能。利用TraceDebug 類,可以將有關錯誤和應用程序執行的信息記錄到日誌、文本文件或其他設備中,以便在隨後進行分析。

      下面列出了六個寫入跟蹤信息的 Debug Members 和 Trace 方法。

Assert:指定的文本;如果未指定任何文本,則爲“調用堆棧”。只有當 Assert 語句中以參數形式指定的條件爲false 時,纔會寫入輸出。

Fail:指定的文本;如果未指定任何文本,則爲“調用堆棧”。

Write:指定的文本。

WriteIf:如果滿足 WriteIf 語句中以參數形式指定的條件,則爲指定的文本。

WriteLine:指定的文本和一個回車。

WriteLineIf:如果滿足 WriteLineIf 語句中以參數形式指定的條件,則爲指定的文本和一個回車。

 

1:Trace 和 Debug區別

      TraceDebug 類基本相同,不同的只是 Trace 類的過程和函數默認爲編譯成發佈版本。

 

2:什麼是Listeners

      Listenters屬性,它是TraceListenerCollection類型(TraceSource類和TraceListener類),給類屬性控制跟蹤信息輸出的方向,可以是控制檯(add(TextWriterTraceListener(new Console.Out))),文件(add(TextWriterTraceListener(new IO.File.CreateText(“output.txt”))等。Listenters集合中的成員包括TextWriterTraceListener,DefaultTraceListener,EventLogTraceListener,WebPageTraceListener等。而TextWriterTraceListener的子類又有ConsoleTraceListener, DelimitedListTraceListener,XmlWriterTraceListener,EventSchemaTraceListener。

     您可以通過實現您自己的偵聽器來生成自定義的結果。 所有自定義偵聽器都應支持文章開頭表中的六個方法。

     以下的例子說明輸出的消息將會在控制檯、TXT文件以及系統日誌中均被記錄。

            TextWriterTraceListener tr1 = new TextWriterTraceListener(System.Console.Out);
            Debug.Listeners.Add(tr1);
            TextWriterTraceListener tr2 = new TextWriterTraceListener(System.IO.File.CreateText("output.txt"));
            Debug.Listeners.Add(tr2);
            EventLogTraceListener tr3 = new EventLogTraceListener();
            Debug.Listeners.Add(tr3);

3:跟蹤開關

      除了指定Listener外,要控制消息是否被輸出,還需要指定跟蹤開關。跟蹤開關用於啓用、禁用和篩選跟蹤輸出。

      Framework 中提供了三種類型的跟蹤開關:BooleanSwitch 類、TraceSwitch 類和 SourceSwitch 類。BooleanSwitch是最簡單的跟蹤開關,可以指定是否輸出消息。TraceSwitch SourceSwitch 類用於爲特定的跟蹤級別啓用跟蹤開關,以便顯示爲該級別及其下的所有級別指定的 Trace TraceSource 消息。

3.1:使用BooleanSwitch開關

      以下是使用BooleanSwitch的例子:

            TextWriterTraceListener tr1 = new TextWriterTraceListener(System.Console.Out);
            Debug.Listeners.Add(tr1);
            TextWriterTraceListener tr2 = new TextWriterTraceListener(System.IO.File.CreateText("output.txt"));
            Debug.Listeners.Add(tr2);
            EventLogTraceListener tr3 = new EventLogTraceListener();
            Debug.Listeners.Add(tr3);

            bool someBizCondition = true;
            BooleanSwitch bs = new BooleanSwitch("DataMessageSwitch", "DataMessageSwitch des");
            bs.Enabled = true;
            Debug.WriteLineIf(someBizCondition, "log....");
            Debug.Flush();

      bs.Enabled設置爲true或者false,並不會使程序自動決定是否輸出信息。

      如果不使用代碼方式,而是使用配置文件的方式,是在 <configuration> 標記之後,但在 </configuration> 標記之前添加相應的 XML 來配置您的開關。如下:

<system.diagnostics>
   <switches>
      <add name="DataMessagesSwitch" value="1" />
   </switches>
</system.diagnostics>
 

3.2:使用TraceSwitch開關

      TraceSwitch類可以通過使用跟蹤開關來篩選消息,通過Level屬性來獲取或設置開關級別。0、1、2、3 和 4 分別對應於 OffErrorWarningInfoVerbose。任何大於 4 的數字都會被當作 Verbose,任何小於零的數字都會被當作 Off

      以下的例子,用代碼的方式來演示使用TraceSwitch來設置跟蹤開關:

            TextWriterTraceListener tr1 = new TextWriterTraceListener(System.Console.Out);
            Debug.Listeners.Add(tr1);
            TextWriterTraceListener tr2 = new TextWriterTraceListener(System.IO.File.CreateText("output.txt"));
            Debug.Listeners.Add(tr2);
            EventLogTraceListener tr3 = new EventLogTraceListener();
            Debug.Listeners.Add(tr3);

            bool someBizCondition = true;
            TraceSwitch ts = new TraceSwitch("mySwitch", "in the Config file");
            ts.Level = TraceLevel.Verbose;
            Debug.WriteLineIf(ts.TraceError && someBizCondition, "Error!!!");
            Debug.WriteLineIf(ts.TraceWarning && someBizCondition, "Warning!!!");
            Debug.WriteLineIf(ts.TraceInfo && someBizCondition, "Info!!!");
            Debug.WriteLineIf(ts.TraceVerbose && someBizCondition, "Verbose!!!");
            Debug.Flush();

 

       使用XML來配置,如下:

<system.diagnostics>
   <switches>
      <add name="mySwitch" value="1" />
   </switches>
</system.diagnostics>

4:使用TraceSource代替Trace和Debug

       從FRAMEWORK2.0開始,就不建議使用Trace和Debug了,而改而用TraceSouce。TraceSource 旨在用作增強的跟蹤系統,並且可代替較舊的Trace Debug 跟蹤類的靜態方法使用。熟悉的 Trace Debug 類仍然存在,不過建議的做法是使用 TraceSource 類進行跟蹤。

       下面的例子演示使用代碼來實現消息的輸出:

 

        private static TraceSource mySource = new TraceSource("TraceSourceApp");
        static void Main(string[] args)
        {
            mySource.Switch = new SourceSwitch("sourceSwitch", "Error");
            mySource.Listeners.Remove("Default");

            TextWriterTraceListener textListener =  new TextWriterTraceListener("myListener.log");
            textListener.TraceOutputOptions = TraceOptions.DateTime | TraceOptions.Callstack;
            textListener.Filter = new EventTypeFilter(SourceLevels.Error);
            mySource.Listeners.Add(textListener);
            
            ConsoleTraceListener console = new ConsoleTraceListener(false);
            console.Filter = new EventTypeFilter(SourceLevels.Information);
            console.Name = "console";
            mySource.Listeners.Add(console);
            Activity1();

            // Set the filter settings for the 
            // console trace listener.
            mySource.Listeners["console"].Filter =  new EventTypeFilter(SourceLevels.Critical);
            Activity2();

            // Allow the trace source to send messages to 
            // listeners for all event types. 
            mySource.Switch.Level = SourceLevels.All;

            // Change the filter settings for the console trace listener.
            mySource.Listeners["console"].Filter = new EventTypeFilter(SourceLevels.Information);
            Activity3();
            mySource.Close();

            return;
        }
        static void Activity1()
        {
            mySource.TraceEvent(TraceEventType.Error, 1, "Error message.");
            mySource.TraceEvent(TraceEventType.Warning, 2, "Warning message.");
        }
        static void Activity2()
        {
            mySource.TraceEvent(TraceEventType.Critical, 3, "Critical message.");
            mySource.TraceInformation("Informational message.");
        }
        static void Activity3()
        {
            mySource.TraceEvent(TraceEventType.Error, 4, "Error message.");
            mySource.TraceInformation("Informational message.");
        }

      以上代碼,如果使用配置文件的方式實現,如下:

  <system.diagnostics>
    <sources>
      <source name="TraceSourceApp" switchName="sourceSwitch" switchType="System.Diagnostics.SourceSwitch">
        <listeners>
          <add name="console" type="System.Diagnostics.ConsoleTraceListener">
            <filter type="System.Diagnostics.EventTypeFilter" initializeData="Warning"/>
          </add>
          <add name="myListener" type="System.Diagnostics.TextWriterTraceListener" initializeData="myListener.log" 
               traceOutputOptions="Callstack">
            <filter type="System.Diagnostics.EventTypeFilter" initializeData="Error"></filter>
          </add>
          <remove name="Default"/>
        </listeners>
      </source>
    </sources>
    <switches>
      <add name="sourceSwitch" value="Warning"/>
    </switches>
  </system.diagnostics>

      配置文件實現的對應代碼部分爲:

        private static TraceSource mySource = new TraceSource("TraceSourceApp");
        static void Main(string[] args)
        {
            Activity1();
            Activity2();
            Activity3();
            mySource.Close();
            return;
        }
        static void Activity1()
        {
            mySource.TraceEvent(TraceEventType.Error, 1, "Error message.");
            mySource.TraceEvent(TraceEventType.Warning, 2, "Warning message.");
        }
        static void Activity2()
        {
            mySource.TraceEvent(TraceEventType.Critical, 3, "Critical message.");
            mySource.TraceInformation("Informational message.");
        }
        static void Activity3()
        {
            mySource.TraceEvent(TraceEventType.Error, 4, "Error message.");
            mySource.TraceInformation("Informational message.");
        }

5:設計一個日誌系統

      有了以上的知識之後,我們就可以來設計一個應用程序的日誌系統(是的,我們不在需要LOG4NET)。我們來假設這個日誌系統最基礎的功能:

      1、以日期來創建日誌名,以免歷史日誌全部寫入一個文件中去;

      2、可以配置想要輸出的日誌類別,如Warning或者Error等;

      3、可以配置想要的日誌內容:如StackTrace或者錯誤信息等;

      思路:

      1、在應用程序啓動代碼中,設置文件名。因爲文件名要根據日期動態生成,所以不能使用配置文件;

      2、其它配置可以配置文件實現;

      3、DO IT;

 

6:關於EventLog

     關於EventLog是一個我不喜歡的功能,更多內容,可參考:http://msdn.microsoft.com/zh-cn/library/aaaxk5bx(VS.80).aspx

 

練習:

1.You are using the Microsoft Visual Studio 2005 IDE to examine the output of a method that returns a string. 
You assign the output of the method to a string variable named fName. You need to write a code segment that
prints the following on a single line     The message. "Test Failed. " The value of fName if the value of fName does 
not equal "John" You also need to ensure that the code segment simultaneously facilitates uninterrupted execution   
of the application. Which code segment should you use?
A. Debug.Assert(fName == "John", "Test FaileD. ", fName);
B. Debug.WriteLineIf(fName != "John", fName, "Test Failed");
C. if (fName != "John") {Debug.Print("Test FaileD. "); Debug.Print(fName);      }
D. if (fName != "John") {Debug.WriteLine("Test FaileD. "); Debug.WriteLine(fName);     }
Answer: B

 

17.You are testing a newly developed method named PersistToDB. This method accepts a parameter of type 
EventLogEntry. This method does not return a value. You need to create a code segment that helps you to test the   
method. The code segment must read entries from the application log of local computers and then pass the entries
on to the PersistToDB method. The code block must pass only events of type Error or Warning from the source
MySource to the PersistToDB method. Which code segment should you use? 
A. EventLog myLog = new EventLog("Application", ".");       
foreach (EventLogEntry entry in myLog.Entries)   
{if (entry.Source == "MySource") {  PersistToDB(entry);     }  }
B. EventLog myLog = new EventLog("Application", ".");        
myLog.Source = "MySource";     
foreach (EventLogEntry entry in myLog.Entries) {          
if (entry.EntryType == (EventLogEntryType.Error & EventLogEntryType.Warning))   
{ PersistToDB(entry);  }}

C. EventLog myLog = new EventLog("Application", ".");        
foreach (EventLogEntry entry in myLog.Entries)   
{ if (entry.Source == "MySource")  
{if (entry.EntryType == EventLogEntryType.Error || entry.EntryType == EventLogEntryType.Warning) 
  {PersistToDB(entry); }  } }
D. EventLog myLog = new EventLog("Application", ".");       
myLog.Source = "MySource";     
foreach (EventLogEntry entry in myLog.Entries)   
{if (entry.EntryType == EventLogEntryType.Error || entry.EntryType == EventLogEntryType.Warning)   
{PersistToDB(entry); }
Answer: C


發佈了3 篇原創文章 · 獲贊 11 · 訪問量 44萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章