close

1 簡介

1.1 Log4net的優點:

幾乎所有的大型應用都會有自己的用於跟蹤調試的API。因為一旦程序被部署以後,就不太可能再利用專門的調試工具了。然而一個管理員可能需要有一套強大的日誌系統來診斷和修復配置上的問題。

經驗表明,日誌記錄往往是軟件開發週期中的重要組成部分。它具有以下幾個優點:它可以提供應用程序運行時的精確環境,可供開發人員盡快找到應用程序中的Bug;一旦在程序中加入了Log 輸出代碼,程序運行過程中就能生成並輸出日誌信息而無需人工干預。另外,日誌信息可以輸出到不同的地方(控制台,文件等)以備以後研究之用。

Log4net就是為這樣一個目的設計的,用於.NET開發環境的日誌記錄包。

1.2 Log4net的安裝:

用戶可以從http://logging.apache.org/log4net/下載log4net的源代碼。解壓軟件包後,在解壓的src目錄下將log4net.sln載入Visual Studio .NET,編譯後可以得到log4net.dll。用戶要在自己的程序裡加入日誌功能,只需將log4net.dll引入工程即可。  

2  Log4net的結構

log4net 有四種主要的組件,分別是Logger(記錄器), Repository(庫), Appender(附著器)以及 Layout(佈局).

2.1 Logger

2.1.1 Logger接口

Logger是應用程序需要交互的主要組件,它用來產生日誌消息。產生的日誌消息並不直接顯示,還要預先經過Layout的格式化處理後才會輸出。

Logger提供了多種方式來記錄一個日誌消息,你可以在你的應用程序裡創建多個Logger,每個實例化的Logger對象都被log4net框架作為命名實體(named entity)來維護。這意味著為了重用Logger對象,你不必將它在不同的類或對像間傳遞,只需要用它的名字為參數調用就可以了。log4net框架使用繼承體系,繼承體系類似於.NET中的名字空間。也就是說,如果有兩個logger,分別被定義為a.b.c和a.b,那麼我們說a.b是a.b.c的祖先。每一個logger都繼承了祖先的屬性

Log4net框架定義了一個ILog接口,所有的logger類都必須實現這個接口。如果你想實現一個自定義的logger,你必須首先實現這個接口。你可以參考在/extension目錄下的幾個例子。

ILog接口的定義如下:

public interface ILog

{

  void Debug(object message);

  void Info(object message);

  void Warn(object message);

  void Error(object message);

  void Fatal(object message);

 

//以上的每一個方法都有一個重載的方法,用來支持異常處理。

//每一個重載方法都如下所示,有一個異常類型的附加參數。

  void Debug(object message, Exception ex);

  // ...

 

//Boolean 屬性用來檢查Logger的日誌級別

//(我們馬上會在後面看到日誌級別)

  bool isDebugEnabled;
  bool isInfoEnabled;

  //… 其他方法對應的Boolean屬性

}

Log4net框架定義了一個叫做LogManager的類,用來管理所有的logger對象。它有一個GetLogger()靜態方法,用我們提供的名字參數來檢索已經存在的Logger對象。如果框架裡不存在該Logger對象,它也會為我們創建一個Logger對象。代碼如下所示:

log4net.ILog log = log4net.LogManager.GetLogger("logger-name");

通常來說,我們會以類(class)的類型(type)為參數來調用GetLogger(),以便跟蹤我們正在進行日誌記錄的類。傳遞的類(class)的類型(type)可以用typeof(Classname)方法來獲得,或者可以用如下的反射方法來獲得:

System.Reflection.MethodBase.GetCurrentMethod().DeclaringType

儘管符號長了一些,但是後者可以用於一些場合,比如獲取調用方法的類(class)的類型(type)。

2.1.2     日誌的級別

正如你在ILog的接口中看到的一樣,有五種不同的方法可以跟蹤一個應用程序。事實上,這五種方法是運作在Logger對像設置的不同日誌優先級別上。這幾種不同的級別是作為常量定義在log4net.spi.Level類中。你可以在程序中使用任何一種方法。但是在最後的發佈中你也許不想讓所有的代碼來浪費你的CPU週期,因此,框架提供了7種級別和相應的Boolean屬性來控制日誌記錄的類型。

 Level有以下幾種取值 

級別 

 

 

 

 

允許的方法 

 

 

 

 

Boolean屬性 

 

 

 

 

優先級別 

 

 

 

 

OFF

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Highest

 

 

 

 

FATAL

 

 

 

 

void Fatal(...);

 

 

 

 

bool IsFatalEnabled;

 

 

 

 

 

 

 

 

RROR

 

 

 

 

void Error(...);

 

 

 

 

bool IsErrorEnabled;

 

 

 

 

 

 

 

 

WARN

 

 

 

 

void Warn(...);

 

 

 

 

bool IsWarnEnabled;

 

 

 

 

 

 

 

 

INFO

 

 

 

 

void Info(...);

 

 

 

 

bool IsInfoEnabled;

 

 

 

 

 

 

 

 

DEBUG

 

 

 

 

void Debug(...);

 

 

 

 

bool IsDebugEnabled;

 

 

 

 

 

 

 

 

ALL

 

 

 

 

 

 

 

 

 

 

 

 

 

Lowest

 

 

 

 

1  Logger的日誌級別  

  在log4net框架裡,通過設置配置文件,每個日誌對象都被分配了一個日誌優先級別。如果沒有給一個日誌對像顯式地分配一個級別,那麼該對像會試圖從他的祖先繼承一個級別值。

ILog接口的每個方法都有一個預先定義好了的級別值。正如你在表1看到的,ILog的Inof()方法具有INFO級別。同樣的,以此類推,Error()方法具有ERROR級別。當我們使用以上的任何一種方法時,log4net框架會檢查日誌對像logger的級別和方法的級別。只有當方法的級別高於日誌級別時,日誌請求才會被接受並執行。

舉例說明,當你創建了一個日誌對象,並且把他的級別設置為INFO。於是框架會設置日誌的每個Boolean屬性。當你調用相應的日誌方法時,框架會檢查相應的Boolean屬性,以決定該方法能不能執行。如下的代碼:
 

Logger.Info("message");
Logger.Debug("message");
Logger.Warn("message");

對於第一種方法,Info()的級別等與日誌的級別(INFO),因此日誌請求會被傳遞,我們可以得到輸出結果」message」。

對於第二種方法,Debug()的級別低於日誌對像logger的日誌級別(INFO),因此,日誌請求被拒絕了,我們得不到任何輸出。同樣的,針對第三行語句,我們可以很容易得出結論。

在表1中有兩個特殊的級別:ALL和OFF。ALL表示允許所有的日誌請求。OFF是拒絕所有的請求。

你也可以顯式地檢查Logger對象的Boolean屬性,如下所示:

if (logger.IsDebugEnabled)
{
  Logger.Debug("message");
}

 

2.2  Repository

Repository主要用於負責日誌對像組織結構的維護。在log4net的以前版本中,框架僅支持分等級的組織結構(hierarchical organization)。這種等級結構本質上是庫的一個實現,並且定義在log4net.Repository.Hierarchy 名字空間中。要實現一個Repository,需要實現log4net.Repository.ILoggerRepository 接口。但是通常並不是直接實現該接口,而是以log4net.Repository.LoggerRepositorySkeleton為基類繼承。體系庫 (hierarchical repository )則由log4net.Repository.Hierarchy.Hierarchy類實現。

如果你是個log4net框架的使用者,而非擴展者,那麼你幾乎不會在你的代碼裡用到Repository的類。相反的,你需要用到LogManager類來自動管理庫和日誌對象。

2.3Appender

一個好的日誌框架應該能夠產生多目的地的輸出。比如說輸出到控制台或保存到一個日誌文件。log4net 能夠很好的滿足這些要求。它使用一個叫做Appender的組件來定義輸出介質。正如名字所示,這些組件把它們附加到Logger日誌組件上並將輸出傳遞到輸出流中。你可以把多個Appender組件附加到一個日誌對像上。 Log4net框架提供了幾個Appender組件。關於log4net提供的Appender組件的完整列表可以在log4net框架的幫助手冊中找到。有了這些現成的Appender組件,一般來說你沒有必要再自己編寫了。但是如果你願意,可以從log4net.Appender.AppenderSkeleton類繼承。

2.4 Appender Filters

一個Appender 對像缺省地將所有的日誌事件傳遞到輸出流。Appender的過濾器(Appender Filters) 可以按照不同的標準過濾日誌事件。在log4net.Filter的名字空間下已經有幾個預定義的過濾器。使用這些過濾器,你可以按照日誌級別範圍過濾日誌事件,或者按照某個特殊的字符串進行過濾。你可以在API的幫助文件中發現更多關於過濾器的信息。

2.5 Layout

Layout 組件用於向用戶顯示最後經過格式化的輸出信息。輸出信息可以以多種格式顯示,主要依賴於我們採用的Layout組件類型。可以是線性的或一個XML文件。Layout組件和一個Appender組件一起工作。API幫助手冊中有關於不同Layout組件的列表。一個Appender對象,只能對應一個Layout對象。要實現你自己的Layout類,你需要從log4net.Layout.LayoutSkeleton類繼承,它實現了ILayout接口。

  3 在程序中使用log4net

 3.1. 在自己的項目中添加對 log4net.dll 的引用。
 3.2. 設置配置文件App.config

示例:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    
<!--如果不用App.config作配置文件,則configSections節不是必須的。-->
    
<configSections>
        
<!--「type」屬性的完整格式為:配置節處理器類名,程序集名稱,Version=程序集版本號,Culture=區域信息,PublicKeyToken=公鑰-->
        
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net" />
    
</configSections>
    
<log4net>
        
<!--日誌記錄器logger,可以有多個-->
        
<logger name="AppLogger">
            
<level value="INFO" />
            
<appender-ref ref="LogFileAppender" />
            
<appender-ref ref="ConsoleAppender" />
        
</logger>
        
<logger name="Form1">
            
<level value="DEBUG" />
            
<appender-ref ref="LogFileAppender" />
        
</logger>
        
<!--所有logger的基,root的設置在所有logger中都起作用。
        當在root和logger中重複設定相同的appender時,你會發現同一日誌信息將被記錄兩次。
-->
        
<!--<root>
            <level value="WARN" />
            <appender-ref ref="LogFileAppender" />
            <appender-ref ref="ConsoleAppender" />
        </root>
-->
        
<!--一個appender可以由多個logger共用,當然一個logger可以指定多個appender。-->
        
<appender name="LogFileAppender" type="log4net.Appender.FileAppender">
            
<param name="File" value="App.log" />
            
<param name="AppendToFile" value="true" />
            
<layout type="log4net.Layout.PatternLayout">
                
<param name="Header" value="[Header]\r\n" />
                
<param name="Footer" value="[Footer]\r\n" />
                
<param name="ConversionPattern" value="%d [%t] %-5p %c [%x] %X{auth} - %m%n" />
            
</layout>
            
<filter type="log4net.Filter.LevelRangeFilter">
                
<param name="LevelMin" value="DEBUG" />
                
<param name="LevelMax" value="FATAL" />
            
</filter>
        
</appender>
        
<appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender">
            
<layout type="log4net.Layout.PatternLayout">
                
<param name="ConversionPattern" value="%d [%t] %-5p %c [%x] %X{auth} - %m%n" />
            
</layout>
        
</appender>
    
</log4net>
</configuration>

3.3 代碼裡實現 

          
  private void btnLog_Click(object sender, System.EventArgs e)
  {
   log4net.ILog log = log4net.LogManager.GetLogger("AppLogger");
   log.Debug("debug");
   log.Info("info");
   log.Warn("warn");
   log.Error("error");
   MessageBox.Show("生成日誌成功!");
  }


arrow
arrow
    全站熱搜
    創作者介紹
    創作者 11 的頭像
    11

    冠霖的部落格

    11 發表在 痞客邦 留言(0) 人氣()