使用Log4net建立日誌及簡單擴展

如何使用Log4net建立日誌及簡單擴展html

1、概述

log4net.Net下一個很是優秀的開源日誌記錄組件。log4net記錄日誌的功能很是強大。它能夠將日誌分不一樣的等級,以不一樣的格式,輸出到不一樣的媒介。本文主要是介紹如何在Visual Studio2008中使用log4net快速建立系統日誌,如何擴展以輸出自定義字段。數據庫

2、一個簡單的使用實例

第一步:在項目中添加對log4net.dll的引用,這裏引用版本是1.2.10.0express

第二步:程序啓動時讀取log4net的配置文件。apache

若是是CS程序,在根目錄的Program.cs中的Main方法中添加:瀏覽器

log4net.Config.XmlConfigurator.Configure();緩存

若是是BS程序,在根目錄的Global.asax.cs(沒有新建一個)中的Application_Start方法中添加:安全

log4net.Config.XmlConfigurator.Configure();網絡

不管BS仍是CS程序均可直接在項目的AssemblyInfo.cs文件裏添加如下的語句:多線程

[assembly: log4net.Config .XmlConfigurator()]app

也可使用自定義的配置文件,具體請參見4.4 關聯配置文件。

第三步:修改配置文件。若是是CS程序,則在默認的App.config文件(沒有新建一個)中添加內容;若是是BS程序,則添加到Web.config文件中,添加內容同樣,這裏再也不列出。

App.config文件添加內容以下:

<?xmlversion="1.0"encoding="utf-8" ?>

<configuration>

  <configSections>

<sectionname="log4net"

type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />

  </configSections>

 

  <log4net>

    <root>

      <levelvalue="WARN" />

      <appender-refref="LogFileAppender" />

      <appender-refref="ConsoleAppender" />

    </root>

 

    <loggername="testApp.Logging">

      <levelvalue="DEBUG"/>

    </logger>

 

    <appendername="LogFileAppender" type="log4net.Appender.FileAppender" >

      <paramname="File"value="log-file.txt" />

      <paramname="AppendToFile"value="true" />

 

      <layouttype="log4net.Layout.PatternLayout">

        <paramname="Header"value="[Header]"/>

        <paramname="Footer"value="[Footer]"/>

        <paramname="ConversionPattern" value="%d [%t] %-5p %c [%x]  - %m%n" />

      </layout>

 

      <filtertype="log4net.Filter.LevelRangeFilter">

        <paramname="LevelMin"value="DEBUG" />

        <paramname="LevelMax"value="WARN" />

      </filter>

    </appender>

 

    <appendername="ConsoleAppender"  type="log4net.Appender.ConsoleAppender" >

      <layouttype="log4net.Layout.PatternLayout">

        <paramname="ConversionPattern"  value="%d [%t] %-5p %c [%x] - %m%n" />

      </layout>

    </appender>

 

  </log4net>

</configuration>

第四步:在程序使用。

log4net.ILog log = log4net.LogManager.GetLogger("testApp.Logging");//獲取一個日誌記錄器

log.Info(DateTime.Now.ToString() + ": login success");//寫入一條新log

這樣就將信息同時輸出到控制檯和寫入到文件名爲「log-file.txt」的文件中,其中「log-file.txt」文件的路徑是當前程序運行所在目錄;也能夠定義爲絕對路徑,配置如:

<paramname="File"value="C:\log-file.txt" />就寫入C盤根目錄下log-file.txt文件中,具體使用技巧參見4.2.1

 

本例的實現請參見8.6附件。

3Log4net的主要組成部分

3.1 Appenders

Appenders用來定義日誌的輸出方式,即日誌要寫到那種介質上去。較經常使用的Log4net已經實現好了,直接在配置文件中調用便可,可參見上面配置文件例子;固然也能夠本身寫一個,須要從log4net.Appender.AppenderSkeleton類繼承。它還能夠經過配置FiltersLayout來實現日誌的過濾和輸出格式。

已經實現的輸出方式有:

AdoNetAppender將日誌記錄到數據庫中。能夠採用SQL和存儲過程兩種方式。

AnsiColorTerminalAppender 將日誌高亮輸出到ANSI終端。

AspNetTraceAppender  能用asp.netTrace的方式查看記錄的日誌。

BufferingForwardingAppender在輸出到子Appenders以前先緩存日誌事件。

ConsoleAppender將日誌輸出到應用程序控制臺。

EventLogAppender將日誌寫到Windows Event Log

FileAppender 將日誌輸出到文件。

ForwardingAppender 發送日誌事件到子Appenders

LocalSyslogAppender 將日誌寫到local syslog service (僅用於UNIX環境下)

MemoryAppender 將日誌存到內存緩衝區。

NetSendAppender將日誌輸出到Windows Messenger service.這些日誌信息將在用戶終端的對話框中顯示。

OutputDebugStringAppender將日誌輸出到Debuger,若是程序沒有Debuger,就輸出到系統Debuger。若是系統Debuger也不可用,將忽略消息。

RemoteSyslogAppender 經過UDP網絡協議將日誌寫到Remote syslog service

RemotingAppender經過.NET Remoting將日誌寫到遠程接收端。

RollingFileAppender將日誌以回滾文件的形式寫到文件中。

SmtpAppender將日誌寫到郵件中。

SmtpPickupDirAppender將消息以文件的方式放入一個目錄中,像IIS SMTP agent這樣的SMTP代理就能夠閱讀或發送它們。

TelnetAppender客戶端經過Telnet來接受日誌事件。

TraceAppender將日誌寫到.NET trace 系統。

UdpAppender將日誌以無鏈接UDP數據報的形式送到遠程宿主或用UdpClient的形式廣播。

3.2 Filters

使用過濾器能夠過濾掉Appender輸出的內容。過濾器一般有如下幾種:

DenyAllFilter阻止全部的日誌事件被記錄

LevelMatchFilter 只有指定等級的日誌事件才被記錄

LevelRangeFilter日誌等級在指定範圍內的事件才被記錄

LoggerMatchFilter Logger名稱匹配,才記錄

PropertyFilter消息匹配指定的屬性值時才被記錄

StringMathFilter消息匹配指定的字符串才被記錄

3.3 Layouts

Layout用於控制Appender的輸出格式,能夠是線性的也能夠是XML

一個Appender只能有一個Layout

最經常使用的Layout應該是經典格式的PatternLayout,其次是SimpleLayoutRawTimeStampLayoutExceptionLayout。而後還有IRawLayoutXMLLayout等幾個,使用較少。Layout能夠本身實現,須要從log4net.Layout.LayoutSkeleton類繼承,來輸出一些特殊須要的格式,在後面擴展時就從新實現了一個Layout

SimpleLayout簡單輸出格式,只輸出日誌級別與消息內容。

RawTimeStampLayout 用來格式化時間,在向數據庫輸出時會用到。

樣式如「yyyy-MM-dd HH:mm:ss

ExceptionLayout須要給Logger的方法傳入Exception對象做爲參數才起做用,不然就什麼也不輸出。輸出的時候會包含MessageTrace

PatterLayout使用最多的一個Layout,能輸出的信息不少,使用方式可參見上面例子中的配置文件。PatterLayout的格式化字符串見文後附註8.1

3.4 Loggers

Logger是直接和應用程序交互的組件。Logger只是產生日誌,而後由它引用的Appender記錄到指定的媒介,並由Layout控制輸出格式。

Logger提供了多種方式來記錄一個日誌消息,也能夠有多個Logger同時存在。每一個實例化的Logger對象對被log4net做爲命名實體(Named Entity)來維護。log4net使用繼承體系,也就是說假如存在兩個Logger,名字分別爲a.b.ca.b。那麼a.b就是a.b.c的祖先。每一個Logger都繼承了它祖先的屬性。全部的Logger都從Root繼承, Root自己也是一個Logger

日誌的等級,它們由高到底分別爲:

OFF > FATAL > ERROR > WARN > INFO > DEBUG  > ALL 

高於等級設定值方法(如何設置參見「配置文件詳解」)都能寫入日誌,Off全部的寫入方法都不寫到日誌裏,ALL則相反。例如當咱們設成Info時,logger.Debug就會被忽略而不寫入文件,可是FATAL, ERROR,WARN,INFO會被寫入,由於他們等級高於INFO

在具體寫日誌時,通常能夠這樣理解日誌等級:

FATAL(致命錯誤):記錄系統中出現的能使用系統徹底失去功能,服務中止,系統崩潰等使系統沒法繼續運行下去的錯誤。例如,數據庫沒法鏈接,系統出現死循環。

ERROR(通常錯誤):記錄系統中出現的致使系統不穩定,部分功能出現混亂或部分功能失效一類的錯誤。例如,數據字段爲空,數據操做不可完成,操做出現異常等。

WARN(警告):記錄系統中不影響系統繼續運行,但不符合系統運行正常條件,有可能引發系統錯誤的信息。例如,記錄內容爲空,數據內容不正確等。

INFO(通常信息):記錄系統運行中應該讓用戶知道的基本信息。例如,服務開始運行,功能已經開戶等。

DEBUG (調試信息):記錄系統用於調試的一切信息,內容或者是一些關鍵數據內容的輸出。

Logger實現的ILog接口,ILog定義了5個方法(Debug,Inof,Warn,Error,Fatal)分別對不一樣的日誌等級記錄日誌。這5個方法還有5個重載。以Debug爲例說明一下,其它的和它差很少。

ILog中對Debug方法的定義以下:

void Debug(object message);

void Debug(object message, Exception ex);

還有一個布爾屬性:

bool IsDebugEnabled { get; }

若是使用Debug(object message, Exception ex),則不管Layout中是否認義了%exception,默認配置下日誌都會輸出Exception。包括ExceptionMessageTrace。若是使用Debug(object message),則日誌是不會輸出Exception

最後還要說一個LogManager類,它用來管理全部的Logger。它的GetLogger靜態方法,能夠得到配置文件中相應的Logger

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

3.5 Object Renders

它將告訴logger如何把一個對象轉化爲一個字符串記錄到日誌裏。(ILog中定義的接口接收的參數是Object,而不是String。)

例如你想把Orange對象記錄到日誌中,但此時logger只會調用Orange默認的ToString方法而已。因此要定義一個OrangeRender類實現log4net.ObjectRender.IObjectRender接口,而後註冊它(咱們在本文中的擴展不使用這種方法,而是直接實現一個自定義的Layout)。這時logger就會知道如何把Orange記錄到日誌中了。

3.6 Repository

Repository主要用於日誌對象組織結構的維護。

4、配置文件詳解

4.1 配置文件構成

主要有兩大部分,一是申明一個名爲「log4net「的自定義配置節,以下所示:

  <configSections>

<sectionname="log4net"

type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />

  </configSections>

二是<log4net>節的具體配置,這是下面要重點說明的。

4.1.1<log4net>

全部的配置都要在<log4net>元素裏定義。

支持的屬性:

debug

可選,取值是truefalse,默認是false。設置爲true,開啓log4net的內部調試。

update

可選,取值是Merge(合併)Overwrite(覆蓋),默認值是Merge。設置爲Overwrite,在提交配置的時候會重置已經配置過的庫。

threshold

可選,取值是repository(庫)中註冊的level,默認值是ALL

支持的子元素:

appender

0或多個

logger

0或多個

renderer

0或多個

root

最多一個

param

0或多個

 

4.1.2<root>

實際上就是一個根logger,全部其它logger都默認繼承它,若是配置文件裏沒有顯式定義,則框架使用根日誌中定義的屬性root元素沒有屬性。

支持的子元素:

appender-ref

0個或多個,要引用的appender的名字。

level

最多一個。只有在這個級別或之上的事件纔會被記錄。

param

0個或多個,設置一些參數。

 

4.1.3<logger>

支持的屬性:

name

必須的,logger的名稱

additivity

可選,取值是truefalse,默認值是true。設置爲false時將阻止父logger中的appender

支持的子元素:

appender-ref

0個或多個,要引用的appender的名字。

level

最多一個。只有在這個級別或之上的事件纔會被記錄。

param

0個或多個,設置一些參數。

 

4.1.4<appender>

定義日誌的輸出方式,只能做爲 log4net 的子元素。name屬性必須惟一,type屬性必須指定。

支持的屬性:

name

必須的,Appender對象的名稱

type

必須的,Appender對象的輸出類型

支持的子元素:

appender-ref

0個或多個,容許此appender引用其餘appender,並非因此appender類型都支持。

filter

0個或多個,定義此app使用的過濾器。

layout

最多一個。定義appender使用的輸出格式。

param

0個或多個,設置Appender類中對應的屬性的值。

實際上<appender>所能包含的子元素遠不止上面4個。

 

4.1.5<layout>

佈局,只能做爲<appender>的子元素。

支持的屬性:

type

必須的,Layout的類型

支持的子元素:

param

0個或多個,設置一些參數。

 

4.1.6<filter>

過濾器,只能做爲<appender>的子元素。

支持的屬性:

type

必須的,Filter的類型

支持的子元素:

param

0個或多個,設置一些參數。

 

4.1.7<param>

<param>元素能夠是何元素的子元素。

支持的屬性:

name

必須的,取值是父對象的參數名。

value

可選的,valuetype中,必須有一個屬性被指定。value是一個能被轉化爲參數值的字符串。

type

可選的,valuetype中,必須有一個屬性被指定。type是一個類型名,若是type不是在log4net程序集中定義的,就須要使用全名。

支持的子元素:

param

0個或多個,設置一些參數。

 

4.2 <appender>配置

   <appender>在配置文件中至少有一個,也能夠有多個,有些<appender>類型還能夠引用其餘<appender>類型,具體參數可參見上表。

下面只對寫入回滾文件與輸出到數據庫(這裏使用SQL數據庫)配置體會說一下,其餘配置可參考官方網站:http://logging.apache.org/log4net/release/config-examples.html

4.2.1寫入回滾文件

    <appendername="ReflectionLayout"type="log4net.Appender.RollingFileAppender,log4net">

<!--日誌文件路徑,「/」與「\」做用相同,到達的目錄相同,文件夾不存在則新建 -->

<!--按文件大小方式輸出時在這裏指定文件名,而且當天的日誌在下一天時在文件名後自動追加當天日期造成新文件。-->

<!按照日期形式輸出時,直接鏈接元素DatePatternvalue造成文件路徑。此處使用這種方式 -->

<!--param的名稱,能夠直接查對應的appender類的屬性名便可,這裏要查的就是RollingFileAppender類的屬性 -->

      <paramname="File"value="D:/Log/" />

 

      <!--是否追加到文件-->

      <paramname="AppendToFile"value="true" />

 

      <!--記錄日誌寫入文件時,不鎖定文本文件,防止多線程時不能寫Log,官方說線程非安全-->

      <lockingModeltype="log4net.Appender.FileAppender+MinimalLock" />

 

      <!使用Unicode編碼-->

      <Encodingvalue="UTF-8" />

 

      <!--最多產生的日誌文件數,超過則只保留最新的n個。設定值value="1"爲不限文件數-->

      <paramname="MaxSizeRollBackups"value="10" />

 

      <!--是否只寫到一個文件中-->

      <paramname="StaticLogFileName"value="false" />

 

      <!--按照何種方式產生多個日誌文件(日期[Date],文件大小[Size],混合[Composite])-->

      <paramname="RollingStyle"value="Composite" />

 

      <!--按日期產生文件夾和文件名[在日期方式與混合方式下使用]-->

<!此處按日期產生文件夾,文件名固定。注意&quot;的位置-->

      <paramname="DatePattern"value="yyyy-MM-dd/&quot;ReflectionLayout.log&quot;"  />

<!這是按日期產生文件夾,並在文件名前也加上日期-->

      <param name="DatePattern" value="yyyyMMdd/yyyyMMdd&quot;-TimerServer.log&quot;"  />

<!這是先按日期產生文件夾,再造成下一級固定的文件夾>

      <param name="DatePattern" value="yyyyMMdd/&quot;TimerServer/TimerServer.log&quot;"  />

 

      <!--每一個文件的大小。只在混合方式與文件大小方式下使用。

超出大小後在全部文件名後自動增長正整數從新命名,數字最大的最先寫入。

可用的單位:KB|MB|GB。不要使用小數,不然會一直寫入當前日誌-->

      <paramname="maximumFileSize"value="500KB" />

 

<!--計數類型爲123-->
      
<paramname="CountDirection"value="1"/>

 

<!過濾設置,LevelRangeFilter爲使用的過濾器。 -->

      <filtertype="log4net.Filter.LevelRangeFilter">

        <paramname="LevelMin"value="DEBUG" />

        <paramname="LevelMax"value="WARN" />

      </filter>

 

      <!--記錄的格式。通常用log4net.Layout.PatternLayout佈局-->

<!此處用繼承了log4net.Layout.PatternLayout的自定義佈局,TGLog.ExpandLayout2

爲命名空間。%property{Operator}%property{Action}是自定義的輸出->

      <layouttype="TGLog.ExpandLayout2.ReflectionLayout,TGLog">

        <paramname="ConversionPattern"

 value="記錄時間:%date 線程ID:[%thread] 日誌級別:%-5level 記錄類:%logger     操做者ID%property{Operator} 操做類型:%property{Action}%n             當前機器名:%property%n當前機器名及登陸用戶:%username %n               記錄位置:%location%n 消息描述:%property{Message}%n                    異常:%exception%n 消息:%message%newline%n%n" />

      </layout>

</appender>

注意這些配置屬性有些是可選的,若是須要,必定要寫正確,不然要麼輸出的不是本身想要的結果,要麼乾脆不輸出任何信息。

4.2.1寫入SQL數據庫

須要在相應的數據庫中準備好一張表,建立語句以下:

CREATE TABLE [Log] (

[ID] [int] IDENTITY (1, 1) NOT NULL ,

[Date] [datetime] NOT NULL ,

[Thread] [varchar] (100) COLLATE Chinese_PRC_CI_AS NULL ,

[Level] [varchar] (100) COLLATE Chinese_PRC_CI_AS NULL ,

[Logger] [varchar] (200) COLLATE Chinese_PRC_CI_AS NULL ,

[Operator] [int] NULL ,

[Message] [text] COLLATE Chinese_PRC_CI_AS NULL ,

[ActionType] [int] NULL ,

[Operand] [varchar] (300) COLLATE Chinese_PRC_CI_AS NULL ,

[IP] [varchar] (20) COLLATE Chinese_PRC_CI_AS NULL ,

[MachineName] [varchar] (100) COLLATE Chinese_PRC_CI_AS NULL ,

[Browser] [varchar] (50) COLLATE Chinese_PRC_CI_AS NULL ,

[Location] [text] COLLATE Chinese_PRC_CI_AS NULL ,

[Exception] [text] COLLATE Chinese_PRC_CI_AS NULL

)

<appendername="ADONetAppender"type="log4net.Appender.ADONetAppender,log4net">

<!--BufferSize爲緩衝區大小,只有日誌記錄超設定值纔會一塊寫入到數據庫-->

<bufferSizevalue="10" /><!或寫爲<param name="BufferSize" value="10" />-->

 

<!--引用-->

<connectionTypevalue="System.Data.SqlClient.SqlConnection, System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />

 

<!--鏈接數據庫字符串-->

<connectionStringvalue="data source=.;initial catalog=Test;integrated security=false;persist security info=True;User ID=sa;Password=;" />

 

<!--插入到表Log-->

<commandTextvalue="INSERT INTO Log ([Date],[Thread],[Level],[Logger],[Operator],[Message],[ActionType],[Operand],[IP],[MachineName],[Browser],[Location],[Exception]) VALUES (@log_date, @thread, @log_level, @logger,@operator, @message,@action_type,@operand,@ip,@machineName,@browser,@location,@exception)" />

 

<!日誌記錄時間,RawTimeStampLayout爲默認的時間輸出格式 -->

      <parameter>

        <parameterNamevalue="@log_date" />

        <dbTypevalue="DateTime" />

        <layouttype="log4net.Layout.RawTimeStampLayout" />

      </parameter>

 

      <!--線程號-->

      <parameter>

        <parameterNamevalue="@thread" />

        <dbTypevalue="String" />

<!長度不能夠省略,不然不會輸出-->

        <sizevalue="100" />

        <layouttype="log4net.Layout.PatternLayout">

          <conversionPatternvalue="%thread" />

        </layout>

      </parameter>

 

      <!--日誌等級-->

      <parameter>

        <parameterNamevalue="@log_level" />

        <dbTypevalue="String" />

        <sizevalue="100" />

        <layouttype="log4net.Layout.PatternLayout">

          <conversionPatternvalue="%level" />

        </layout>

      </parameter>

 

      <!--日誌記錄類名稱-->

      <parameter>

        <parameterNamevalue="@logger" />

        <dbTypevalue="String" />

        <sizevalue="200" />

        <layouttype="log4net.Layout.PatternLayout">

          <conversionPatternvalue="%logger" />

        </layout>

      </parameter>

     

      <!--操做者。這個是自定義的輸出字段,使用從新實現的佈局器ReflectionLayout -->

      <parameter>

        <parameterNamevalue="@operator" />

<!設置爲Int32時只有bufferSizevalue<="1"才正確輸出,沒有找出緣由-->

        <dbTypevalue="Int16" />

        <layouttype="TGLog.ExpandLayout2.ReflectionLayout,TGLog">

          <conversionPatternvalue="%property{Operator}" />

        </layout>

      </parameter>

 

      <!--操做對象-->

      <parameter>

        <parameterNamevalue="@operand" />

        <dbTypevalue="String" />

        <sizevalue="300" />

        <layouttype="TGLog.ExpandLayout2.ReflectionLayout,TGLog">

          <conversionPatternvalue="%property{Operand}" />

        </layout>

      </parameter>

 

      <!IP地址-->

      <parameter>

        <parameterNamevalue="@ip" />

        <dbTypevalue="String" />

        <sizevalue="20" />

        <layouttype="TGLog.ExpandLayout2.ReflectionLayout,TGLog">

          <conversionPatternvalue="%property{IP}" />

        </layout>

      </parameter>

 

      <!--機器名-->

      <parameter>

        <parameterNamevalue="@machineName" />

        <dbTypevalue="String" />

        <sizevalue="100" />

        <layouttype="TGLog.ExpandLayout2.ReflectionLayout,TGLog">

          <conversionPatternvalue="%property{MachineName}" />

        </layout>

      </parameter>

 

      <!--瀏覽器-->

      <parameter>

        <parameterNamevalue="@browser" />

        <dbTypevalue="String" />

        <sizevalue="50" />

        <layouttype="TGLog.ExpandLayout2.ReflectionLayout,TGLog">

          <conversionPatternvalue="%property{Browser}" />

        </layout>

      </parameter>

     

      <!日誌消息-->

      <parameter>

        <parameterNamevalue="@message" />

        <dbTypevalue="String" />

        <sizevalue="3000" />

        <layouttype="TGLog.ExpandLayout2.ReflectionLayout,TGLog">

          <conversionPatternvalue="%property{Message}" />

        </layout>

      </parameter>

 

      <!--動做類型-->

      <parameter>

        <parameterNamevalue="@action_type" />

        <dbTypevalue="Int16" />

        <layouttype="TGLog.ExpandLayout2.ReflectionLayout,TGLog">

          <conversionPatternvalue="%property{ActionType}" />

        </layout>

      </parameter>

 

      <!記錄日誌的位置-->

      <parameter>

        <parameterNamevalue="@location" />

        <dbTypevalue="String" />

        <sizevalue="2000" />

        <layouttype="log4net.Layout.PatternLayout">

          <conversionPatternvalue="%location" />

        </layout>

      </parameter>

     

      <!異常信息。ExceptionLayout爲異常輸出的默認格式-->

      <parameter>

        <parameterNamevalue="@exception" />

        <dbTypevalue="String" />

        <sizevalue="4000" />

        <layouttype="log4net.Layout.ExceptionLayout" />

      </parameter>

</appender>

注意:

向表中輸出的字段不能多於數據表自己字段,而反之則能夠,但這些多餘字段必定使其能夠爲空,不然便寫不到數據庫;

輸出字段的類型必定是對應數據表字段數據類型能夠隱式轉換的,並且長度也不能超過,不然也不能寫入;

數據表字段設置儘可能能夠爲空,這樣能夠避免一條日誌記錄存在空數據致使後面的日誌都記錄不了。

4.3<logger>的配置

在配置文件<appender>中的配置好了輸出的介質,格式,過濾方式,還要定義日誌對象<logger>

在框架的體系裏,全部的日誌對象都是根日誌(root logger)的後代。 所以若是一個日誌對象沒有在配置文件裏顯式定義,則框架使用根日誌中定義的屬性。在<root>標籤裏,能夠定義level級別值和Appender的列表。若是沒有定義LEVEL的值,則缺省爲DEBUG。能夠經過<appender-ref>標籤訂義日誌對象使用的Appender對象。<appender-ref>聲明瞭在其餘地方定義的Appender對象的一個引用。在一個logger對象中的設置會覆蓋根日誌的設置。而對Appender屬性來講,子日誌對象則會繼承父日誌對象的Appender列表。這種缺省的行爲方式也能夠經過顯式地設定<logger>標籤的additivity屬性爲false而改變。

<root>不顯式申明時使用默認的配置。我以爲在使用時不定義<root>,自定義多個<logger>,在程序中記錄日誌時直接使用<logger>name來查找相應的<logger>,這樣更靈活一些。例如:

<!--同時寫兩個文件和數據庫-->

<loggername="ReflectionLayout">

      <levelvalue="DEBUG"/>

      <appender-refref="HashtableLayout"/>

      <appender-refref="ReflectionLayout"/>

      <appender-refref="ADONetAppender"/>

</logger>

4.4關聯配置文件

log4net默認關聯的是應用程序的配置文件App.config(BS程序是Web.config),可使用程序集自定義屬性來進行設置。下面來介紹一下這個自定義屬性:

log4net.Config.XmlConifguratorAttribute

 

XmlConfiguratorAttribute3個屬性:

ConfigFile 配置文件的名字,文件路徑相對於應用程序目錄

(AppDomain.CurrentDomain.BaseDirectory)ConfigFile屬性不能和ConfigFileExtension屬性一塊兒使用。

ConfigFileExtension 配置文件的擴展名,文件路徑相對於應用程序的目錄。ConfigFileExtension屬性不能和ConfigFile屬性一塊兒使用。

Watch 若是將Watch屬性設置爲true,就會監視配置文件。當配置文件發生變化的時候,就會從新加載。

若是ConfigFileConfigFileExtension都沒有設置,則使用應用程序的配置文件App.configWeb.config)。

 

能夠在項目的AssemblyInfo.cs文件裏添加如下的語句:

 //監視默認的配置文件,App.exe.config   

[assembly: log4net.Config.XmlConfigurator(Watch = true)]

 

//監視配置文件,App.exe.log4net

[assembly: log4net. Config.XmlConfigurator(ConfigFileExtension = "log4net", Watch = true)]

 

//使用配置文件log4net.config,不監視改變。注意log4net.config文件的目錄,BS程序在站點目錄//下,CS則在應用程序啓動目錄下,如調試時在\bin\Debug下,通常將文件屬性的文件輸出目錄調爲//始終複製便可

[assembly: log4net. Config.XmlConfigurator(ConfigFile = "log4net.config")]

 

//使用配置文件log4net.config,不監視改變

[assembly: log4net. Config.XmlConfigurator()]

 

也能夠在Global.asaxApplication_Start裏或者是Program.cs中的Main方法中添加,注意這裏必定是絕對路徑,以下所示:

//這是在BS程序下,使用自定義的配置文件log4net.xml,使用Server.MapPath("~") + //@"\log4net.xml來取得路徑。 \log4net.xml爲相對於站點的路徑

// ConfigureAndWatch()至關於Configure(Watch = true)

log4net.Config.XmlConfigurator.ConfigureAndWatch(

new System.IO.FileInfo(Server.MapPath("~") + @"\log4net.xml"));

//這是在CS程序下,能夠用如下方法得到:

string assemblyFilePath = Assembly.GetExecutingAssembly().Location;

string assemblyDirPath = Path.GetDirectoryName(assemblyFilePath);

string configFilePath = assemblyDirPath + " \\log4net.xml";

log4net.Config.XmlConfigurator.ConfigureAndWatch(

new FileInfo(configFilePath));

 

或直接使用絕對路徑:

//使用自定義的配置文件,直接絕對路徑爲:c:/log4net.config

log4net.Config.XmlConfigurator.Configure(new System.IO.FileInfo(@"c:/log4net.config"));

 

5、如何記錄日誌

Log4net使用很方便,先申明一個封裝類ILog的對象,以下:

log4net.ILog log = log4net.LogManager.GetLogger("ReflectionLayout");

其中"ReflectionLayout"即是咱們自定義的日誌對象<logger>name的值。

對應5個日誌輸出級別,log5 個方法,每一個方法都有兩個重載,使用以下:

try

            {

                log.Debug("這是一個測試!");

            }

            catch(Exception ec)

            {

                log.Error("出現錯誤!", ec);

         }

若是咱們須要輸出的消息是要區別開來,不按一個字符串所有輸出,就須要進行一些擴展了。

6Log4net的簡單擴展

6.1經過重寫佈局Layout輸出傳入的message對象的屬性

6.1.1重寫Layout

經過繼承log4net.Layout.PatternLayout類,使用log4net.Core.LoggingEvent類的方法獲得了要輸出的message類的名稱,而後經過反射獲得各個屬性的值,使用PatternLayoutAddConverter方法傳入獲得的值。這裏注意要引用用到的類的命名空間。

代碼見附註8.2

 

6.1.2配置相應的配置文件

配置文件其餘地方不用改動,只是須要改動<appender>中的<layout>。例如:

<layouttype="TGLog.ExpandLayout2.ReflectionLayout,TGLog">

        <paramname="ConversionPattern"

 value="記錄時間:%date    操做者ID%property{Operator}             

操做類型:%property{Action}%n  消息描述:%property{Message}%n                    異常:%exception%n " />

      </layout>

其中<layout>type由原來的log4net.Layout.PatternLayout換爲自定義的TGLog.ExpandLayout2.ReflectionLayoutTGLog.ExpandLayout2爲命名空間)。%property{Operator}輸出的即爲message類對象的屬性Operator的值。數據庫配置一樣,相應的字段若是是自定義的,則輸出選用自定義的<layout>。例:

<!--動做類型-->

  <parameter>

      <parameterNamevalue="@action_type" />

      <dbTypevalue="Int16" />

      <layouttype="TGLog.ExpandLayout2.ReflectionLayout,TGLog">

         <conversionPatternvalue="%property{ActionType}" />

      </layout>

  </parameter>

6.1.3程序中如何使用

和通常使用方法基本相同,只是傳入的參數是一個自定義的類,類的屬性和配置文件中<layout>全部的%property{屬性}是一致的,即%property{屬性}在輸出的時候就查找傳入message類中有無對應的屬性,若是有就輸出值,沒有則輸出null。例:

log4net.ILog log = log4net.LogManager.GetLogger("ReflectionLayout");

try

            {

                log.Debug(new LogMessage(

1,

"操做對象:0",

 (int)TGLog.ActionType.Other,

 "這是四個參數測試")

);

            }

            catch(Exception ec)

            {

                log.Error(new LogMessage(

                                    1,

                                    "操做對象:0",

                                    (int)TGLog.ActionType.Other,

                                    "這是所有參數測試",

                                    "192.168.1.1",

                                    "MyComputer",

                                    "Maxthon(MyIE2)Fans"),

                         ec

);

      }

LogMessage的所有屬性的構造方法以下:

public LogMessage(

            int operatorID,

            string operand,

            int ActionType,

            string message,

            string ip,

            string machineName,

            string browser

            )

     {

            this.ActionType = ActionType;

            this.Operator = operatorID;

            this.Message = message;

            this.Operand = operand;

            this.IP = ip;

            this.Browser = browser;

            this.MachineName = machineName;

}

6.2經過從新實現ILog接口來增長輸入的參數

6.2.1重寫LogImplLogManager類及實現ILog接口

這種方式是經過構造一個名爲IMyLog接口,是繼承Ilog接口而來,而後分別在MyLogImplMyLogManager從新實現IMyLog接口,增長了每種方法的參數。MyLogImplMyLogManager分別繼承LogImplLogManager而來。

代碼分別見8.38.48.5

6.2.2配置相應的配置文件

配置文件其餘地方不用改動,只是須要改動<appender>中的<layout>元素nameConversionPatternvalue中輸出格式。例如:

<layouttype=" log4net.Layout.PatternLayout ">

        <paramname="ConversionPattern"

 value="記錄時間:%date    操做者ID%property{Operator}             

操做類型:%property{Action}%n  消息描述:%property{Message}%n                    異常:%exception%n " />

      </layout>

%property{參數}中的參數在MyLogImpl類中定義,如語句:

loggingEvent.Properties["Operator"] = operatorID;

就定義了Operator輸出參數,即%property{Operator}輸出的即爲IMyLog中的參數operatorID的值。

數據庫配置一樣。例:

<!--動做類型-->

  <parameter>

      <parameterNamevalue="@action_type" />

      <dbTypevalue="Int16" />

      <layouttype=" log4net.Layout.PatternLayout ">

         <conversionPatternvalue="%property{ActionType}" />

      </layout>

  </parameter>

6.2.3程序中如何使用

先引用IMyLogMyLogManager所在的命名空間,建立一個IMyLog對象,myLog5 個方法,每一個方法都有四個重載,增長了多參數的重載。例:

IMyLog myLog = MyLogManager.GetLogger("ExpandILog");

try

            {

myLog.Debug("這是一個參數重載測試!");          

}

            catch(Exception ec)

            {

                log.Error(

                          1,

                          "操做對象:0",

                          (int)TGLog.ActionType.Other,

                          "這是所有參數測試",

                          "192.168.1.1",

                          "MyComputer",

                          "Maxthon(MyIE2)Fans",

                          ec

);

      }

7、總結

Log4net 功能不少,這裏只是對已經嘗試用過的功能總結一下,普通寫日誌已經足夠。須要注意的是:

1.            Log4net自己也有一些缺陷,好比一個記錄引發了log4net自己的異常,就會使後面的日誌沒法記錄下來,尤爲是在寫入數據庫時。例如使用6.1擴展後,int型的屬性在<appender >的元素<bufferSize>設置不爲1時,<dbTypevalue="Int32" />時,就不能輸出到數據庫,而<dbTypevalue="Int16" />則沒任何問題。

2.            Log4net自己出現了異常,好比配置文件出現錯誤,有些日誌輸出方式會記錄下這些異常,例如應用程序控制臺;有些則不會輸出這些錯誤,如數據庫與文件。

3.            擴展時也會留下一些問題。例如在使用6.1擴展輸出字段時就會出現,在log.debug(object message)中,若是message是一個自定義的類,屬性與配置文件中輸出設置也一致,構造函數時也只構造一個參數的實例,寫文件與寫數據庫都成功,而將message按沒有擴展的方式直接傳入一個字符串,即log.debug(「信息內容」)使用則只能寫入文件,而數據庫則沒寫入。自定義的Layout 就是繼承默認的PatternLayout原本不該該出錯,但出現了問題。緣由分析是自定義的message類有類型爲int的屬性,做爲一個對象傳入時在默認值0,而直接使用字符串則int型的字段得不到默認值,引起異常。因此建議在有擴展存在時,最好多設幾個<logger>,區分清楚,按照統一的形式記錄日誌,不要混合使用。

4.            配置文件的設置必定要準確,在一點不正確就會致使日誌不能正常輸出,因此在配置時先從最簡單的開始,同時輸出方式選擇一種能輸出log4net自己異常的方式,成功後一點一點加在新配置,這樣出錯了也容易找到那個地方配置有問題。

5.            log4net擴展性很強,幾乎全部的組件均可以重寫,在配置文件中配置好就可使用。

8、附註:

8.1PatterLayout格式化字符表

轉換字符

效果

a

等價於appdomain

appdomain

引起日誌事件的應用程序域的友好名稱。(使用中通常是可執行文件的名字。)

c

等價於 logger

C

等價於 type

class

等價於 type

d

等價於 date

date

發生日誌事件的本地時間。 使用 DE>%utcdate 輸出UTC時間。date後面還能夠跟一個日期格式,用大括號括起來。DE>例如:%date{HH:mm:ss,fff}或者%date{dd MMM yyyy HH:mm:ss,fff}。若是date後面什麼也不跟,將使用ISO8601 格式

日期格式和.NetDateTime類的ToString方法中使用的格式是同樣。

另外log4net還有3個本身的格式Formatter 它們是 "ABSOLUTE", "DATE""ISO8601"分別表明 AbsoluteTimeDateFormatter, DateTimeDateFormatterIso8601DateFormatter。例如: %date{ISO8601}%date{ABSOLUTE}

它們的性能要好於ToString

exception

異常信息

日誌事件中必須存了一個異常對象,若是日誌事件不包含沒有異常對象,將什麼也不輸出。異常輸出完畢後會跟一個換行。通常會在輸出異常前加一個換行,並將異常放在最後。

F

等價於 file

file

發生日誌請求的源代碼文件的名字。

警告:只在調試的時候有效。調用本地信息會影響性能。

identity

當前活動用戶的名字(Principal.Identity.Name).

警告:會影響性能。(我測試的時候%identity返回都是空的。)

l

等價於 location

L

等價於 line

location

引起日誌事件的方法(包括命名空間和類名),以及所在的源文件和行號。

警告:會影響性能。沒有pdb文件的話,只有方法名,沒有源文件名和行號。

level

日誌事件等級

line

引起日誌事件的行號

警告:會影響性能。

logger

記錄日誌事件的Logger對象的名字。

可使用精度說明符控制Logger的名字的輸出層級,默認輸出全名。

注意,精度符的控制是從右開始的。例如:logger 名爲 "a.b.c" 輸出模型爲 %logger{2} ,將輸出"b.c"

m

等價於 message

M

等價於 method

message

由應用程序提供給日誌事件的消息。

mdc

MDC (舊爲:ThreadContext.Properties) 如今是事件屬性的一部分。 保留它是爲了兼容性,它等價於 property

method

發生日誌請求的方法名(只有方法名而已)。

警告:會影響性能。

n

等價於 newline

newline

換行符

ndc

NDC (nested diagnostic context)

p

等價於 level

P

等價於 property

properties

等價於 property

property

輸出事件的特殊屬性。例如: %property{user} 輸出user屬性。屬性是由loggersappenders添加到時間中的。 有一個默認的屬性"DE>log4net:HostName"老是會有。DE>

%property將輸出全部的屬性

(擴展後可使用)

 

r

等價於 timestamp

t

等價於 thread

timestamp

從程序啓動到事件發生所通過的毫秒數。

thread

引起日誌事件的線程,若是沒有線程名就使用線程號。

type

引起日誌請求的類的全名。.

可使用精度控制符。例如: 類名是 "log4net.Layout.PatternLayout", 格式模型是 %type{1} 將輸出"PatternLayout"。(也是從右開始的。)

警告:會影響性能。

u

等價於 identity

username

當前用戶的WindowsIdentity。(相似:HostName\Username

警告:會影響性能。

utcdate

發生日誌事件的UTC時間。DE>後面還能夠跟一個日期格式,用大括號括起來。DE>例如:%utcdate{HH:mm:ss,fff}或者%utcdate{dd MMM yyyy HH:mm:ss,fff}。若是utcdate後面什麼也不跟,將使用ISO8601 格式

日期格式和.NetDateTime類的ToString方法中使用的格式是同樣。

另外log4net還有3個本身的格式Formatter 它們是 "ABSOLUTE", "DATE""ISO8601"分別表明 AbsoluteTimeDateFormatter, DateTimeDateFormatterIso8601DateFormatter。例如: %date{ISO8601}%date{ABSOLUTE}

它們的性能要好於ToString

w

等價於 username

x

等價於 ndc

X

等價於 mdc

%

%%輸出一個百分號

關於調用本地信息(caller location information)的說明:

%type %file %line %method %location %class %C %F %L %l %M 都會調用本地信息。這樣作會影響性能。本地信息使用System.Diagnostics.StackTrace獲得。.Net 1.0 不支持System.Diagnostics.StackTrace 類。

本地信息在調試模式下能夠正常獲取,在非調試模式下可能獲取不到,或只能獲取一部分。(根據個人測試,實際上是須要有一個程序數據庫(.pdb)文件。)

%property屬性要用代碼來設置才能使用(也就是擴展一下),

默認屬性log4net:HostName不用設置。

轉義字符的修飾符:

Format modifier

left justify

minimum width

maximum width

comment

%20logger

false

20

none

若是logger名不足20個字符,就在左邊補空格。

%-20logger

true

20

none

若是logger名不足20個字符,就在右邊補空格。

%.30logger

NA

none

30

超過30個字符將截斷。

%20.30logger

false

20

30

logger名要在2030之間,少了在左邊補空格,多了截斷。

%-20.30logger

true

20

30

logger名要在2030之間,少了在右邊補空格,多了截斷。

8.2Layout類代碼

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using log4net.Layout;

using log4net.Layout.Pattern;

using System.Reflection;

using System.Collections;

using FastReflectionLib;

 

namespace TGLog.ExpandLayout2

{

    public class ReflectionLayout : PatternLayout

    {

        public ReflectionLayout()

        {

            this.AddConverter("property", typeof(ReflectionPatternConverter));

        }

    }

 

    public class ReflectionPatternConverter : PatternLayoutConverter

    {

        protected override void Convert(

System.IO.TextWriter writer,

 log4net.Core.LoggingEvent loggingEvent

)

        {

            if (Option != null)

            {

                // 寫入指定鍵的值

                WriteObject(

writer,

 loggingEvent.Repository,

 LookupProperty(Option,

 loggingEvent)

);

            }

            else

            {

                // 寫入全部關鍵值對

                WriteDictionary(

writer,

loggingEvent.Repository,

 loggingEvent.GetProperties()

);

            }

        }

 

        ///<summary>

        ///經過反射獲取傳入的日誌對象的某個屬性的值

        ///</summary>

        ///<param name="property"></param>

        ///<returns></returns>

        private object LookupProperty(

string property,

 log4net.Core.LoggingEvent loggingEvent)

        {

            object propertyValue = string.Empty;

 

            PropertyInfo propertyInfo =

loggingEvent.MessageObject.GetType().GetProperty(property);

            if (propertyInfo != null)

            {

                propertyValue =

propertyInfo.GetValue(loggingEvent.MessageObject, null);

            }

            return propertyValue;

        }

    }

}

8.3 MyLogImpl類代碼

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using log4net.Core;

 

namespace TGLog.ExpandILog

{

    public class MyLogImpl : LogImpl, IMyLog

    {

        ///<summary>

        /// The fully qualified name of this declaring type not the type of any subclass.

        ///</summary>

        private readonly static Type ThisDeclaringType = typeof(MyLogImpl);

 

        public MyLogImpl(ILogger logger)

            : base(logger)

        {       

        }

 

        #region Implementation of IMyLog

 

        public void Debug(int operatorID, string operand, int actionType,object message,

 string ip, string browser, string machineName)

        {

            Debug(operatorID,  operand,  actionType, message,

  ip,  browser, machineName, null);

        }

 

        public void Debug(int operatorID, string operand, int actionType,object message,

string ip, string browser, string machineName, System.Exception t)

        {

            if (this.IsDebugEnabled)

            {

                LoggingEvent loggingEvent =

new LoggingEvent(ThisDeclaringType, Logger.Repository,

                                       Logger.Name, Level.Info, message, t);

                loggingEvent.Properties["Operator"] = operatorID;

                loggingEvent.Properties["Operand"] = operand;

                loggingEvent.Properties["ActionType"] = actionType;

                loggingEvent.Properties["IP"] = ip;

                loggingEvent.Properties["Browser"] = browser;

                loggingEvent.Properties["MachineName"] = machineName;

                Logger.Log(loggingEvent);

            }

        }

 

        public void Info(int operatorID, string operand, int actionType, object message,

string ip, string browser, string machineName)

        {

            Info(operatorID, operand, actionType, message, ip, browser, machineName, null);

        }

 

        public void Info(int operatorID, string operand, int actionType, object message,

 string ip, string browser, string machineName, System.Exception t)

        {

            if (this.IsInfoEnabled)

            {

                LoggingEvent loggingEvent =

 new LoggingEvent(ThisDeclaringType, Logger.Repository,

 Logger.Name, Level.Info, message, t);

                loggingEvent.Properties["Operator"] = operatorID;

                loggingEvent.Properties["Operand"] = operand;

                loggingEvent.Properties["ActionType"] = actionType;

                loggingEvent.Properties["IP"] = ip;

                loggingEvent.Properties["Browser"] = browser;

                loggingEvent.Properties["MachineName"] = machineName;

                Logger.Log(loggingEvent);

            }

        }

 

        public void Warn(int operatorID, string operand, int actionType, object message,

string ip, string browser, string machineName)

        {

            Warn(operatorID, operand, actionType, message, ip, browser, machineName, null);

        }

 

        public void Warn(int operatorID, string operand, int actionType, object message,

 string ip, string browser, string machineName, System.Exception t)

        {

            if (this.IsWarnEnabled)

            {

                LoggingEvent loggingEvent =

 new LoggingEvent(ThisDeclaringType, Logger.Repository,

Logger.Name, Level.Info, message, t);

                loggingEvent.Properties["Operator"] = operatorID;

                loggingEvent.Properties["Operand"] = operand;

                loggingEvent.Properties["ActionType"] = actionType;

                loggingEvent.Properties["IP"] = ip;

                loggingEvent.Properties["Browser"] = browser;

                loggingEvent.Properties["MachineName"] = machineName;

                Logger.Log(loggingEvent);

            }

        }

 

        public void Error(int operatorID, string operand, int actionType, object message,

string ip, string browser, string machineName)

        {

            Error(operatorID, operand, actionType, message, ip, browser, machineName, null);

        }

 

        public void Error(int operatorID, string operand, int actionType, object message,

 string ip, string browser, string machineName, System.Exception t)

        {

            if (this.IsErrorEnabled)

            {

                LoggingEvent loggingEvent =

 new LoggingEvent(ThisDeclaringType, Logger.Repository,

 Logger.Name, Level.Info, message, t);

                loggingEvent.Properties["Operator"] = operatorID;

                loggingEvent.Properties["Operand"] = operand;

                loggingEvent.Properties["ActionType"] = actionType;

                loggingEvent.Properties["IP"] = ip;

                loggingEvent.Properties["Browser"] = browser;

                loggingEvent.Properties["MachineName"] = machineName;

                Logger.Log(loggingEvent);

            }

        }

 

        public void Fatal(int operatorID, string operand, int actionType, object message,

 string ip, string browser, string machineName)

        {

            Fatal(operatorID, operand, actionType, message, ip, browser, machineName, null);

        }

 

        public void Fatal(int operatorID, string operand, int actionType, object message,

 string ip, string browser, string machineName, System.Exception t)

        {

            if (this.IsFatalEnabled)

            {

                LoggingEvent loggingEvent =

 new LoggingEvent(ThisDeclaringType, Logger.Repository,

                                       Logger.Name, Level.Info, message, t);

                loggingEvent.Properties["Operator"] = operatorID;

                loggingEvent.Properties["Operand"] = operand;

                loggingEvent.Properties["ActionType"] = actionType;

                loggingEvent.Properties["IP"] = ip;

                loggingEvent.Properties["Browser"] = browser;

                loggingEvent.Properties["MachineName"] = machineName;

                Logger.Log(loggingEvent);

            }

        }

        #endregion Implementation of IMyLog

    }

}

 

8.4 MyLogManager類代碼

#region Copyright & License

//

// Copyright 2001-2005 The Apache Software Foundation

//

// Licensed under the Apache License, Version 2.0 (the "License");

// you may not use this file except in compliance with the License.

// You may obtain a copy of the License at

//

// http://www.apache.org/licenses/LICENSE-2.0

//

// Unless required by applicable law or agreed to in writing, software

// distributed under the License is distributed on an "AS IS" BASIS,

// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

// See the License for the specific language governing permissions and

// limitations under the License.

//

#endregion

 

using System;

using System.Reflection;

using System.Collections;

using log4net;

using log4net.Core;

using log4net.Repository;

using log4net.Repository.Hierarchy;

 

namespace TGLog.ExpandILog

{

    public class MyLogManager

    {

        #region Static Member Variables

 

        ///<summary>

        /// The wrapper map to use to hold the <see cref="EventIDLogImpl"/> objects

        ///</summary>

        private static readonly WrapperMap s_wrapperMap = new WrapperMap(new WrapperCreationHandler(WrapperCreationHandler));

 

        #endregion

 

        #region Constructor

 

        ///<summary>

        /// Private constructor to prevent object creation

        ///</summary>

        private MyLogManager() { }

 

        #endregion

 

        #region Type Specific Manager Methods

 

        ///<summary>

        /// Returns the named logger if it exists

        ///</summary>

        ///<remarks>

        ///<para>If the named logger exists (in the default hierarchy) then it

        /// returns a reference to the logger, otherwise it returns

        ///<c>null</c>.</para>

        ///</remarks>

        ///<param name="name">The fully qualified logger name to look for</param>

        ///<returns>The logger found, or null</returns>

        public static IMyLog Exists(string name)

        {

            return Exists(Assembly.GetCallingAssembly(), name);

        }

 

        ///<summary>

        /// Returns the named logger if it exists

        ///</summary>

        ///<remarks>

        ///<para>If the named logger exists (in the specified domain) then it

        /// returns a reference to the logger, otherwise it returns

        ///<c>null</c>.</para>

        ///</remarks>

        ///<param name="domain">the domain to lookup in</param>

        ///<param name="name">The fully qualified logger name to look for</param>

        ///<returns>The logger found, or null</returns>

        public static IMyLog Exists(string domain, string name)

        {

            return WrapLogger(LoggerManager.Exists(domain, name));

        }

 

        ///<summary>

        /// Returns the named logger if it exists

        ///</summary>

        ///<remarks>

        ///<para>If the named logger exists (in the specified assembly's domain) then it

        /// returns a reference to the logger, otherwise it returns

        ///<c>null</c>.</para>

        ///</remarks>

        ///<param name="assembly">the assembly to use to lookup the domain</param>

        ///<param name="name">The fully qualified logger name to look for</param>

        ///<returns>The logger found, or null</returns>

        public static IMyLog Exists(Assembly assembly, string name)

        {

            return WrapLogger(LoggerManager.Exists(assembly, name));

        }

 

        ///<summary>

        /// Returns all the currently defined loggers in the default domain.

        ///</summary>

        ///<remarks>

        ///<para>The root logger is <b>not</b> included in the returned array.</para>

        ///</remarks>

        ///<returns>All the defined loggers</returns>

        public static IMyLog[] GetCurrentLoggers()

        {

            return GetCurrentLoggers(Assembly.GetCallingAssembly());

        }

 

        ///<summary>

        /// Returns all the currently defined loggers in the specified domain.

        ///</summary>

        ///<param name="domain">the domain to lookup in</param>

        ///<remarks>

        /// The root logger is <b>not</b> included in the returned array.

        ///</remarks>

        ///<returns>All the defined loggers</returns>

        public static IMyLog[] GetCurrentLoggers(string domain)

        {

            return WrapLoggers(LoggerManager.GetCurrentLoggers(domain));

        }

 

        ///<summary>

        /// Returns all the currently defined loggers in the specified assembly's domain.

        ///</summary>

        ///<param name="assembly">the assembly to use to lookup the domain</param>

        ///<remarks>

        /// The root logger is <b>not</b> included in the returned array.

        ///</remarks>

        ///<returns>All the defined loggers</returns>

        public static IMyLog[] GetCurrentLoggers(Assembly assembly)

        {

            return WrapLoggers(LoggerManager.GetCurrentLoggers(assembly));

        }

 

        ///<summary>

        /// Retrieve or create a named logger.

        ///</summary>

        ///<remarks>

        ///<para>Retrieve a logger named as the <paramref name="name"/>

        /// parameter. If the named logger already exists, then the

        /// existing instance will be returned. Otherwise, a new instance is

        /// created.</para>

        ///

        ///<para>By default, loggers do not have a set level but inherit

        /// it from the hierarchy. This is one of the central features of

        /// log4net.</para>

        ///</remarks>

        ///<param name="name">The name of the logger to retrieve.</param>

        ///<returns>the logger with the name specified</returns>

        public static IMyLog GetLogger(string name)

        {

            return GetLogger(Assembly.GetCallingAssembly(), name);

        }

 

        ///<summary>

        /// Retrieve or create a named logger.

        ///</summary>

        ///<remarks>

        ///<para>Retrieve a logger named as the <paramref name="name"/>

        /// parameter. If the named logger already exists, then the

        /// existing instance will be returned. Otherwise, a new instance is

        /// created.</para>

        ///

        ///<para>By default, loggers do not have a set level but inherit

        /// it from the hierarchy. This is one of the central features of

        /// log4net.</para>

        ///</remarks>

        ///<param name="domain">the domain to lookup in</param>

        ///<param name="name">The name of the logger to retrieve.</param>

        ///<returns>the logger with the name specified</returns>

        public static IMyLog GetLogger(string domain, string name)

        {

            return WrapLogger(LoggerManager.GetLogger(domain, name));

        }

 

        ///<summary>

        /// Retrieve or create a named logger.

        ///</summary>

        ///<remarks>

        ///<para>Retrieve a logger named as the <paramref name="name"/>

        /// parameter. If the named logger already exists, then the

        /// existing instance will be returned. Otherwise, a new instance is

        /// created.</para>

        ///

        ///<para>By default, loggers do not have a set level but inherit

        /// it from the hierarchy. This is one of the central features of

        /// log4net.</para>

        ///</remarks>

        ///<param name="assembly">the assembly to use to lookup the domain</param>

        ///<param name="name">The name of the logger to retrieve.</param>

        ///<returns>the logger with the name specified</returns>

        public static IMyLog GetLogger(Assembly assembly, string name)

        {

            return WrapLogger(LoggerManager.GetLogger(assembly, name));

        }

 

        ///<summary>

        /// Shorthand for <see cref="LogManager.GetLogger(string)"/>.

        ///</summary>

        ///<remarks>

        /// Get the logger for the fully qualified name of the type specified.

        ///</remarks>

        ///<param name="type">The full name of <paramref name="type"/> will

        /// be used as the name of the logger to retrieve.</param>

        ///<returns>the logger with the name specified</returns>

        public static IMyLog GetLogger(Type type)

        {

            return GetLogger(Assembly.GetCallingAssembly(), type.FullName);

        }

 

        ///<summary>

        /// Shorthand for <see cref="LogManager.GetLogger(string)"/>.

        ///</summary>

        ///<remarks>

        /// Get the logger for the fully qualified name of the type specified.

        ///</remarks>

        ///<param name="domain">the domain to lookup in</param>

        ///<param name="type">The full name of <paramref name="type"/> will

        /// be used as the name of the logger to retrieve.</param>

        ///<returns>the logger with the name specified</returns>

        public static IMyLog GetLogger(string domain, Type type)

        {

            return WrapLogger(LoggerManager.GetLogger(domain, type));

        }

 

        ///<summary>

        /// Shorthand for <see cref="LogManager.GetLogger(string)"/>.

        ///</summary>

        ///<remarks>

        /// Get the logger for the fully qualified name of the type specified.

        ///</remarks>

        ///<param name="assembly">the assembly to use to lookup the domain</param>

        ///<param name="type">The full name of <paramref name="type"/> will

        /// be used as the name of the logger to retrieve.</param>

        ///<returns>the logger with the name specified</returns>

        public static IMyLog GetLogger(Assembly assembly, Type type)

        {

            return WrapLogger(LoggerManager.GetLogger(assembly, type));

        }

 

        #endregion

 

        #region Extension Handlers

 

        ///<summary>

        /// Lookup the wrapper object for the logger specified

        ///</summary>

        ///<param name="logger">the logger to get the wrapper for</param>

        ///<returns>the wrapper for the logger specified</returns>

        private static IMyLog WrapLogger(ILogger logger)

        {

            return (IMyLog)s_wrapperMap.GetWrapper(logger);

        }

 

        ///<summary>

        /// Lookup the wrapper objects for the loggers specified

        ///</summary>

        ///<param name="loggers">the loggers to get the wrappers for</param>

        ///<returns>Lookup the wrapper objects for the loggers specified</returns>

        private static IMyLog[] WrapLoggers(ILogger[] loggers)

        {

            IMyLog[] results = new IMyLog[loggers.Length];

            for (int i = 0; i < loggers.Length; i++)

            {

                results[i] = WrapLogger(loggers[i]);

            }

            return results;

        }

 

        ///<summary>

        /// Method to create the <see cref="ILoggerWrapper"/> objects used by

        /// this manager.

        ///</summary>

        ///<param name="logger">The logger to wrap</param>

        ///<returns>The wrapper for the logger specified</returns>

        private static ILoggerWrapper WrapperCreationHandler(ILogger logger)

        {

            return new MyLogImpl(logger);

        }

        #endregion

    }

}

8.5 IMyLog類代碼

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using log4net;

 

namespace TGLog.ExpandILog

{

    public interface IMyLog : ILog

    {

        void Debug(int operatorID, string operand, int actionType, object message,

string ip, string browser, string machineName);

        void Debug(int operatorID, string operand, int actionType,object message,

string ip, string browser, string machineName, Exception t);

 

        void Info(int operatorID, string operand, int actionType, object message,

string ip, string browser, string machineName);

        void Info(int operatorID, string operand, int actionType, object message,

string ip, string browser, string machineName, Exception t);

 

        void Warn(int operatorID, string operand, int actionType, object message,

string ip, string browser, string machineName);

        void Warn(int operatorID, string operand, int actionType, object message,

 string ip, string browser, string machineName, Exception t);

 

        void Error(int operatorID, string operand, int actionType, object message,

string ip, string browser, string machineName);

        void Error(int operatorID, string operand, int actionType, object message,

string ip, string browser, string machineName, Exception t);

 

        void Fatal(int operatorID, string operand, int actionType, object message,

string ip, string browser, string machineName);

        void Fatal(int operatorID, string operand, int actionType, object message,

string ip, string browser, string machineName, Exception t);

    }

}

8.6附件

使用log4net記錄日誌

8.7參考

1http://peibing211.blog.163.com/blog/static/37116360200992811595469/

2http://www.cnblogs.com/qiangzi/archive/2009/09/10/1541023.html

3http://blog.chinaunix.net/u/23701/showart_1414206.html

4http://itrust.cnblogs.com/archive/2005/01/25/97225.html

5http://www.cnitblog.com/seeyeah/archive/2009/09/20/61491.aspx

6http://www.cnblogs.com/zhmore/archive/2009/03/19/1416707.html

7http://blog.shinylife.net/blog/article.asp?id=948

8http://www.cnblogs.com/manhoo/archive/2009/06/25/1511066.html

 

 

出處:https://www.cnblogs.com/longshizhong/archive/2009/11/25/1610452.html

相關文章
相關標籤/搜索