一、前言 在項目中,對項目的日誌收集是非常重要的,這裡我就說說代碼的異常日誌收集。收集異常日誌,有很多第三方成熟的框架,我這裡就介紹一下我常用的Log4net。 Log4Net介紹 Log4net 是 Apache 下一款非常著名的基於.net開發的記錄日誌開源組件,它是Log4j 的一個克隆版。L ...
一、前言
在項目中,對項目的日誌收集是非常重要的,這裡我就說說代碼的異常日誌收集。收集異常日誌,有很多第三方成熟的框架,我這裡就介紹一下我常用的Log4net。
Log4Net介紹
Log4net 是 Apache 下一款非常著名的基於.net開發的記錄日誌開源組件,它是Log4j 的一個克隆版。Log4net記錄日誌的功能非常強大。它可以將日誌分不同的等級,比不同的樣式,將日誌輸出到不同的媒介,並且可以進行擴展。
官方地址:https://logging.apache.org/log4net/
二、配置說明
關於Log4Net的配置介紹,園子裡面有很多介紹,我看過一篇我到目前為止,介紹得最最詳細的博文,這裡我就直接轉過來了,因為我自認為也寫不出更加詳細的配置說明,轉載過來的還有一個目的,就是為了預防博主刪博文,之前就遇到過,博主不知道是刪了還是搬家了,收藏的博文就404了。
這裡我根據實際使用情況,只轉載了一些重要的配置說明,如果園友想看全文,連接地址:https://www.cnblogs.com/lzrabbit/archive/2012/03/23/2413180.html
這篇文章寫了有幾年了,估計Log4Net的配置形式有些修改,園友使用時可以自己調整。
1、Log4net的主要組成部分
1.1 Appenders
Appenders用來定義日誌的輸出方式,即日誌要寫到那種介質上去。較常用的Log4net已經實現好了,直接在配置文件中調用即可,可參見上面配置文件例子;當然也可以自己寫一個,需要從log4net.Appender.AppenderSkeleton類繼承。它還可以通過配置Filters和Layout來實現日誌的過濾和輸出格式。
AdoNetAppender 將日誌記錄到資料庫中。可以採用SQL和存儲過程兩種方式。
AnsiColorTerminalAppender 將日誌高亮輸出到ANSI終端。
AspNetTraceAppender 能用asp.net中Trace的方式查看記錄的日誌。
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的形式廣播。
1.2、Filters
使用過濾器可以過濾掉Appender輸出的內容。過濾器通常有以下幾種:
DenyAllFilter 阻止所有的日誌事件被記錄
LevelMatchFilter 只有指定等級的日誌事件才被記錄
LevelRangeFilter 日誌等級在指定範圍內的事件才被記錄
LoggerMatchFilter 與Logger名稱匹配,才記錄
PropertyFilter 消息匹配指定的屬性值時才被記錄
StringMathFilter 消息匹配指定的字元串才被記錄
1.3、Layouts
Layout用於控制Appender的輸出格式,可以是線性的也可以是XML。
一個Appender只能有一個Layout。
最常用的Layout應該是經典格式的PatternLayout,其次是SimpleLayout,RawTimeStampLayout和ExceptionLayout。然後還有IRawLayout,XMLLayout等幾個,使用較少。Layout可以自己實現,需要從log4net.Layout.LayoutSkeleton類繼承,來輸出一些特殊需要的格式,在後面擴展時就重新實現了一個Layout。
SimpleLayout簡單輸出格式,只輸出日誌級別與消息內容。
RawTimeStampLayout 用來格式化時間,在向資料庫輸出時會用到。樣式如“yyyy-MM-dd HH:mm:ss“
ExceptionLayout需要給Logger的方法傳入Exception對象作為參數才起作用,否則就什麼也不輸出。輸出的時候會包含Message和Trace。
PatterLayout使用最多的一個Layout,能輸出的信息很多,使用方式可參見上面例子中的配置文件。PatterLayout的格式化字元串見文後 三、附註。
1.4、Loggers
Logger是直接和應用程式交互的組件。Logger只是產生日誌,然後由它引用的Appender記錄到指定的媒介,並由Layout控制輸出格式。
Logger提供了多種方式來記錄一個日誌消息,也可以有多個Logger同時存在。每個實例化的Logger對象對被log4net作為命名實體(Named Entity)來維護。log4net使用繼承體系,也就是說假如存在兩個Logger,名字分別為a.b.c和a.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。包括Exception的Message和Trace。如果使用Debug(object message),則日誌是不會輸出Exception。
最後還要說一個LogManager的類,它用來管理所有的Logger。它的GetLogger靜態方法,可以獲得配置文件中相應的Logger:
log4net.ILog log = log4net.LogManager.GetLogger("logger-name");
1.5、Object Renders
它將告訴logger如何把一個對象轉化為一個字元串記錄到日誌里。(ILog中定義的介面接收的參數是Object,而不是String。)
例如你想把Orange對象記錄到日誌中,但此時logger只會調用Orange預設的ToString方法而已。所以要定義一個OrangeRender類實現log4net.ObjectRender.IObjectRender介面,然後註冊它(我們在本文中的擴展不使用這種方法,而是直接實現一個自定義的Layout)。這時logger就會知道如何把Orange記錄到日誌中了。
1.6、Repository
Repository主要用於日誌對象組織結構的維護
2、配置文件詳解
2.1、配置文件構成
主要有兩大部分:
一是申明一個名為“log4net“的自定義配置節,如下所示:
<configSections> <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" /> </configSections>
二是<log4net>節的具體配置,這是下麵要重點說明的。
2.1.1、log4net
所有的配置都要在<log4net>元素里定義。
支持的屬性:
debug |
可選,取值是true或false,預設是false。設置為true,開啟log4net的內部調試。 |
update |
可選,取值是Merge(合併)或Overwrite(覆蓋),預設值是Merge。設置為Overwrite,在提交配置的時候會重置已經配置過的庫。 |
threshold |
可選,取值是repository(庫)中註冊的level,預設值是ALL。 |
支持的子元素:
appender |
0或多個 |
logger |
0或多個 |
renderer |
0或多個 |
root |
最多一個 |
param |
0或多個 |
2.1.2、root
實際上就是一個根logger,所有其它logger都預設繼承它,如果配置文件里沒有顯式定義,則框架使用根日誌中定義的屬性。root元素沒有屬性。
支持的子元素:
appender-ref |
0個或多個,要引用的appender的名字。 |
level |
最多一個。 只有在這個級別或之上的事件才會被記錄。 |
param |
0個或多個, 設置一些參數。 |
2.1.3、logger
支持的屬性:
name |
必須的,logger的名稱 |
additivity |
可選,取值是true或false,預設值是true。設置為false時將阻止父logger中的appender。 |
支持的子元素:
appender-ref |
0個或多個,要引用的appender的名字。 |
level |
最多一個。 只有在這個級別或之上的事件才會被記錄。 |
param |
0個或多個, 設置一些參數。 |
2.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個。
2.1.5、layout
佈局,只能作為<appender>的子元素。
支持的屬性:
type |
必須的,Layout的類型 |
支持的子元素:
param |
0個或多個, 設置一些參數。 |
2.1.6、filter
過濾器,只能作為<appender>的子元素。
支持的屬性:
type |
必須的,Filter的類型 |
支持的子元素:
param |
0個或多個, 設置一些參數。 |
2.1.7、param
<param>元素可以是任何元素的子元素。
支持的屬性:
name |
必須的,取值是父對象的參數名。 |
value |
可選的,value和type中,必須有一個屬性被指定。value是一個能被轉化為參數值的字元串。 |
type |
可選的,value和type中,必須有一個屬性被指定。type是一個類型名,如果type不是在log4net程式集中定義的,就需要使用全名。 |
支持的子元素:
param |
0個或多個, 設置一些參數。 |
2.2、appender配置
<appender>在配置文件中至少有一個,也可以有多個,有些<appender>類型還可以引用其他<appender>類型,具體參數可參見上表。
下麵只對寫入回滾文件與輸出到資料庫(這裡使用SQL資料庫)配置體會說一下,其他配置可參考官方網站:http://logging.apache.org/log4net/release/config-examples.html
2.2.1、寫入回滾文件
下麵就是根據我自己的實際情況,設置的我的配置
<log4net debug="false"> <root> <level value="ALL" /> </root> <logger name="PFTLog"> <level value="DEBUG"/> <appender-ref ref="ErrorRollingFileAppender" /> <appender-ref ref="DebugRollingFileAppender" /> <appender-ref ref="InfoRollingFileAppender" /> </logger> <!--數據日誌--> <appender name="InfoRollingFileAppender" type="log4net.Appender.RollingFileAppender" > <file value="LogFile\Info\" /> <appendToFile value="true" /> <!--記錄日誌寫入文件時,不鎖定文本文件,防止多線程時不能寫Log,官方說線程非安全--> <lockingModel type="log4net.Appender.FileAppender+MinimalLock" /> <Encoding value="UTF-8" /> <!--最多產生的日誌文件數,超過則只保留最新的n個。設定值value="-1"為不限文件數--> <MaxSizeRollBackups value="20" /> <!--是否只寫到一個文件中--> <StaticLogFileName value="false" /> <!--按照何種方式產生多個日誌文件(日期[Date],文件大小[Size],混合[Composite])--> <rollingStyle value="Composite" /> <!--按日期產生文件夾和文件名[在日期方式與混合方式下使用]--> <!--這是按日期產生文件夾,併在文件名前也加上日期--> <datePattern value="yyyyMMdd-"-Info.log"" /> <!--每個文件的大小。 只在混合方式與文件大小方式下使用。 超出大小後在所有文件名後自動增加正整數重新命名,數字最大的最早寫入。可用的單位:KB|MB|GB。 不要使用小數,否則會一直寫入當前日誌--> <maximumFileSize value="1MB" /> <!--計數類型為1,2,3…--> <!--<CountDirection value="1" />--> <!--記錄的格式。一般用log4net.Layout.PatternLayout佈局--> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="%n記錄時間:%date %n線程ID[%thread] %n日誌級別:%-5level %n記錄類:%logger %n擴展信息:%property -%n異常:%exception %n錯誤描述:%message%newline" /> </layout> <filter type="log4net.Filter.LevelRangeFilter"> <param name="LevelMin" value="INFO" /> <param name="LevelMax" value="INFO" /> </filter> </appender> <!--錯誤日誌--> <appender name="ErrorRollingFileAppender" type