Layout
Layout 組件用於向用戶顯示最後經過格式化的輸出信息。輸出信息可以以多種格式顯示,主要依賴於我們采用的Layout組件類型。可以是線性的或一個XML文件。 Layout組件和一個Appender組件一起工作。API幫助手冊中有關於不同Layout組件的列表。一個Appender對象,只能對應一個 Layout對象。要實現你自己的Layout類,你需要從log4net.Layout.LayoutSkeleton類繼承,它實現了ILayout 接口。
4 在程序中使用log4net
在開始對你的程序進行日志記錄前,需要先啟動log4net引擎。這意味著你需要先配置前面提到的三種組件。你可以用兩種方法來設定配置:在單獨的文件中設定配置或在代碼中定義配置。
因為下面幾種原因,推薦在一個單獨的文件中定義配置:
這一點在一些WEB程序和遠程過程調用的程序中有時很重要;
考慮到第一種方法的重要性,我們先看看怎樣在文件中設定配置信息。
(1)定義配置文件
配置信息可以放在如下幾種形式文件的一種中。
在程序的配置文件裡,如AssemblyName.config 或web.config.
在你自己的文件裡。文件名可以是任何你想要的名字,如AppName.exe.xyz等.
log4net框架會在相對於AppDomain.CurrentDomain.BaseDirectory 屬性定義的目錄路徑下查找配置文件。框架在配置文件裡要查找的唯一標識是<log4net>標簽。一個完整的配置文件的例子如下:<?XML version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="log4net"
type="log4net.Config.Log4NetConfigurationSectionHandler,
log4net-net-1.0" />
</configSections>
<log4net>
<root>
<level value="WARN" />
<appender-ref ref="LogFileAppender" />
<appender-ref ref="ConsoleAppender" /></root>
<logger name="testApp.Logging">
<level value="DEBUG"/>
</logger><appender name="LogFileAppender"
type="log4net.Appender.FileAppender" >
<param name="File" value="log-file.txt" />
<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] - %m%n"
/>
</layout>
<filter type="log4net.Filter.LevelRangeFilter">
<param name="LevelMin" value="DEBUG" />
<param name="LevelMax" value="WARN" />
</filter>
</appender>
<appender name="ConsoleAppender"
type="log4net.Appender.ConsoleAppender" >
<layout type="log4net.Layout.PatternLayout">
<param name="ConversionPattern"
value="%d [%t] %-5p %c [%x] - %m%n"
/>
</layout>
</appender>
</log4net>
</configuration>
你可以直接將上面的文本拷貝到任何程序中使用,但是最好還是能夠理解配置文件是怎樣構成的。只有當你需要在應用程序配置文件中使用log4net配置時,才需要在<configSection>標簽中加入<section>配置節點入口。對於其他的單獨文件,只有<log4net>標簽內的文本才是必需的,這些標簽的順序並不是固定的。下面我們依次講解各個標簽內文本的含義:
(2)<root>
<root>
<level value="WARN" />
<appender-ref ref="LogFileAppender" />
<appender-ref ref="ConsoleAppender" />
</root>
在框架的體系裡,所有的日志對象都是根日志(root logger)的後代。因此如果一個日志對象沒有在配置文件裡顯式定義,則框架使用根日志中定義的屬性。在<root>標簽裡,可以定義 level級別值和Appender的列表。如果沒有定義LEVEL的值,則缺省為DEBUG。可以通過<appender-ref>標簽定義日志對象使用的Appender對象。<appender-ref>聲明了在其他地方定義的Appender對象的一個引用。在一個 logger對象中的設置會覆蓋根日志的設置。而對Appender屬性來說,子日志對象則會繼承父日志對象的Appender列表。這種缺省的行為方式也可以通過顯式地設定<logger>標簽的additivity屬性為false而改變。
<logger name="testApp.Logging" additivity="false">
</logger>
Additivity的值缺省是true.
<Logger>
<logger name="testApp.Logging">
<level value="DEBUG"/>
</logger>
<logger> 元素預定義了一個具體日志對象的設置。然後通過調用LogManager.GetLogger(“testAPP.Logging”)函數,你可以檢索具有該名字的日志。如果LogManager.GetLogger(…)打開的不是預定義的日志對象,則該日志對象會繼承根日志對象的屬性。知道了這一點,我們可以說,其實<logger>標簽並不是必須的。
(3) <appender>
<appender name="LogFileAppender"
type="log4net.Appender.FileAppender" >
<param name="File" value="log-file.txt" />
<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 - %m%n"
/>
</layout>
<filter type="log4net.Filter.LevelRangeFilter">
<param name="LevelMin" value="DEBUG" />
<param name="LevelMax" value="WARN" />
</filter>
</appender>
在<root>標簽或單個的<logger>標簽裡的Appender對象可以用<appender>標簽定義。<appender>標簽的基本形式如上面所示。它定義了appender的名字和類型。另外比較重要的是<appender>標簽內部的其他標簽。不同的appender有不同的<param>標簽。在這裡,為了使用 FileAppender,你需要一個文件名作為參數。另外還需要一個在<appender>標簽內部定義一個Layout對象。 Layout對象定義在它自己的<layout>標簽內。<layout>標簽的type屬性定義了Layout的類型(在本例裡是PatternLayout),同時也確定了需要提供的參數值。Header和Footer標簽提供了一個日志會話(logging session)開始和結束時輸出的文字。有關每種appender的具體配置的例子,可以在log4net\doc\manual\example- config-appender.Html中得到。
(4) log4net.Layout.PatternLayout中的轉換模式(ConversionPattern)
%m(message):輸出的日志消息,如ILog.Debug(…)輸出的一條消息
%n(new line):換行
%d(datetime):輸出當前語句運行的時刻
%r(run time):輸出程序從運行到執行到當前語句時消耗的毫秒數
%t(thread id):當前語句所在的線程ID
%p(priority): 日志的當前優先級別,即DEBUG、INFO、WARN…等
%c(class):當前日志對象的名稱,例如:
模式字符串為:%-10c -%m%n
代碼為:
ILog log=LogManager.GetLogger(“Exam.Log”);
log.Debug(“Hello”);
則輸出為下面的形式:
Exam.Log - Hello
%L:輸出語句所在的行號
%F:輸出語句所在的文件名
%-數字:表示該項的最小長度,如果不夠,則用空格填充
例如,轉換模式為%r [%t]%-5p %c - %m%n 的 PatternLayout 將生成類似於以下內容的輸出:
176 [main] INFO org.foo.Bar - Located nearest gas station.
(5) <filter>
最後,讓我們看看在Appender元素裡的<filter>標簽。它定義了應用到Appender對象的過濾器。本例中,我們使用了 LevelRangeFilter過濾器,它可以只記錄LevelMin和LevelMax參數指定的日志級別之間的日志事件。可以在一個 Appender上定義多個過濾器(Filter),這些過濾器將會按照它們定義的順序對日志事件進行過濾。其他過濾器的有關信息可以在log4net的 SDK文檔中找到。
5 使用配置文件
(1)關聯配置文件
當我們創建了上面的配置文件後,我們接下來需要把它和我們的應用聯系起來。缺省的,每個獨立的可執行程序集都會定義它自己的配置。log4net框架使用 log4net.Config.DOMConfiguratorAttribute在程序集的級別上定義配置文件。
例如:可以在項目的AssemblyInfo.cs文件裡添加以下的語句
[assembly:log4net.Config.DOMConfigurator(ConfigFile="filename",
ConfigFileExtension="ext",Watch=true/false)]
ConfigFile:指出了我們的配置文件的路徑及文件名,包括擴展名。
ConfigFileExtension:如果我們對被編譯程序的程序集使用了不同的文件擴展名,那麼我們需要定義這個屬性,缺省的,程序集的配置文件擴展名為”config”。
Watch (Boolean屬性): log4net框架用這個屬性來確定是否需要在運行時監視文件的改變。如果這個屬性為true,那麼FileSystemWatcher將會被用來監視文件的改變,重命名,刪除等事件。
其中:ConfigFile和ConfigFileExtension屬性不能同時使用,ConfigFile指出了配置文件的名字,例如,ConfigFile=”Config.txt”
ConfigFileExtension則是指明了和可執行程序集同名的配置文件的擴展名,例如,應用程序的名稱是”test.exe”,ConfigFileExtension=”txt”,則配置文件就應該是”test.exe.txt” ;
也可以不帶參數應用DOMConfiguratio():
[assembly: log4net.Config.DOMConfigurator()]
也可以在程序代碼中用DOMConfigurator類打開配置文件。類的構造函數需要一個FileInfo對象作參數,以指出要打開的配置文件名。這個方法和前面在程序集裡設置屬性打開一個配置文件的效果是一樣的。log4net.Config.DOMConfigurator.Configure(
new FileInfo("TestLogger.Exe.Config"));
DOMConfigurator 類還有一個方法ConfigureAndWatch(..), 用來配置框架並檢測文件的變化。
以上的步驟總結了和配置相關的各個方面,下面我們將分兩步來使用logger對象。
(2)創建或獲取日志對象
日志對象會使用在配置文件裡定義的屬性。如果某個日志對象沒有事先在配置文件裡定義,那麼框架會根據繼承結構獲取祖先節點的屬性,最終的,會從根日志獲取屬性。如下所示:
Log4net.ILog log = Log4net.LogManager.GetLogger("MyLogger");
(3) 輸出日志信息
可以使用ILog的幾種方法輸出日志信息。你也可以在調用某方法前先檢查IsXXXEnabled布爾變量,再決定是否調用輸出日志信息的函數,這樣可以提高程序的性能。因為框架在調用如ILog.Debug(…)這樣的函數時,也會先判斷是否滿足Level日志級別條件。
if (log.IsDebugEnabled) log.Debug("message");
if (log.IsInfoEnabled) log.Info("message);
6 在程序中配置log4net
除了前面講的用一個配置文件來配置log4net以外,還可以在程序中用代碼來配置log4net框架。如下面的例子:
// 和PatternLayout一起使用FileAppender
log4net.Config.BasicConfigurator.Configure(
new log4net.Appender.FileAppender(
new log4net.Layout.PatternLayout("%d
[%t]%-5p %c [%x] - %m%n"),"testfile.log"));
// using a FileAppender with an XMLLayout
log4net.Config.BasicConfigurator.Configure(
new log4net.Appender.FileAppender(
new log4net.Layout.XMLLayout(),"testfile.XML"));
// using a ConsoleAppender with a PatternLayout
log4net.Config.BasicConfigurator.Configure(
new log4net.Appender.ConsoleAppender(
new log4net.Layout.PatternLayout("%d
[%t] %-5p %c - %m%n")));
// using a ConsoleAppender with a SimpleLayout
log4net.Config.BasicConfigurator.Configure(
new log4net.Appender.ConsoleAppender(new
log4net.Layout.SimpleLayout()));
盡管這裡用代碼配置log4net也很方便,但是你卻不能分別配置每個日志對象。所有的這些配置都是被應用到根日志上的。
log4net.Config.BasicConfigurator 類使用靜態方法Configure 設置一個Appender 對象。而Appender的構造函數又會相應的要求Layout對象。你也可以不帶參數直接調用 BasicConfigurator.Configure(),它會使用一個缺省的PatternLayout對象,在一個 ConsoleAppender中輸出信息。如下所示:
log4net.Config.BasicConfigurator.Configure();
在輸出時會顯示如下格式的信息:
0 [1688] DEBUG log1 A B C - Test
20 [1688] INFO log1 A B C - Test
當log4net框架被配置好以後,就可以如前所述使用日志功能了。
總結
使用log4net可以很方便地為應用添加日志功能。應用Log4net,使用者可以很精確地控制日志信息的輸出,減少了多余信息,提高了日志記錄性能。同時,通過外部配置文件,用戶可以不用重新編譯程序就能改變應用的日志行為,使得用戶可以根據情況靈活地選擇要記錄的信息。