日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

非常完善的Log4net详细说明(转)

發(fā)布時間:2023/12/10 编程问答 68 豆豆
生活随笔 收集整理的這篇文章主要介紹了 非常完善的Log4net详细说明(转) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

最可能來源:https://blog.csdn.net/ydm19891101/article/details/50561638

其它轉(zhuǎn)載者:http://www.cnblogs.com/zhangchenliang/p/4546352.html

1、概述

log4net是.Net下一個非常優(yōu)秀的開源日志記錄組件。log4net記錄日志的功能非常強大。它可以將日志分不同的等級,以不同的格式,輸出到不同的媒介。本文主要是介紹如何在Visual Studio2008中使用log4net快速創(chuàng)建系統(tǒng)日志,如何擴展以輸出自定義字段。

?

2、一個簡單的使用實例

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

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

如果是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()]

也可以使用自定義的配置文件,具體請參見4.4?關(guān)聯(lián)配置文件。

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

App.config文件添加內(nèi)容如下:

<?xml?version="1.0"?encoding="utf-8"??>

<configuration>

??<configSections>

<section?name="log4net"

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

??</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]?"/>

????????<param?name="Footer"?value="[Footer]?"/>

????????<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.ILog?log = log4net.LogManager.GetLogger("testApp.Logging");//獲取一個日志記錄器

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

這樣就將信息同時輸出到控制臺和寫入到文件名為“l(fā)og-file.txt”的文件中,其中“l(fā)og-file.txt”文件的路徑是當(dāng)前程序運行所在目錄;也可以定義為絕對路徑,配置如:

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

?

本例的實現(xiàn)請參見8.6附件。

3、Log4net的主要組成部分

3.1 Appenders

Appenders用來定義日志的輸出方式,即日志要寫到那種介質(zhì)上去。較常用的Log4net已經(jīng)實現(xiàn)好了,直接在配置文件中調(diào)用即可,可參見上面配置文件例子;當(dāng)然也可以自己寫一個,需要從log4net.Appender.AppenderSkeleton類繼承。它還可以通過配置Filters和Layout來實現(xiàn)日志的過濾和輸出格式。

已經(jīng)實現(xiàn)的輸出方式有:

AdoNetAppender?將日志記錄到數(shù)據(jù)庫中。可以采用SQL和存儲過程兩種方式。

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

AspNetTraceAppender??能用asp.net中Trace的方式查看記錄的日志。

BufferingForwardingAppender?在輸出到子Appenders之前先緩存日志事件。

ConsoleAppender?將日志輸出到應(yīng)用程序控制臺。

EventLogAppender?將日志寫到Windows?Event?Log。

FileAppender?將日志輸出到文件。

ForwardingAppender?發(fā)送日志事件到子Appenders。

LocalSyslogAppender?將日志寫到local?syslog?service?(僅用于UNIX環(huán)境下)。

MemoryAppender?將日志存到內(nèi)存緩沖區(qū)。

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

OutputDebugStringAppender?將日志輸出到Debuger,如果程序沒有Debuger,就輸出到系統(tǒng)Debuger。如果系統(tǒng)Debuger也不可用,將忽略消息。

RemoteSyslogAppender?通過UDP網(wǎng)絡(luò)協(xié)議將日志寫到Remote?syslog?service。

RemotingAppender?通過.NET?Remoting將日志寫到遠程接收端。

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

SmtpAppender?將日志寫到郵件中。

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

TelnetAppender?客戶端通過Telnet來接受日志事件。

TraceAppender?將日志寫到.NET?trace?系統(tǒng)。

UdpAppender?將日志以無連接UDP數(shù)據(jù)報的形式送到遠程宿主或用UdpClient的形式廣播。

3.2 Filters

使用過濾器可以過濾掉Appender輸出的內(nèi)容。過濾器通常有以下幾種:

DenyAllFilter?阻止所有的日志事件被記錄

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

LevelRangeFilter?日志等級在指定范圍內(nèi)的事件才被記錄

LoggerMatchFilter?與Logger名稱匹配,才記錄

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

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

3.3 Layouts

Layout用于控制Appender的輸出格式,可以是線性的也可以是XML。

一個Appender只能有一個Layout。

最常用的Layout應(yīng)該是經(jīng)典格式的PatternLayout,其次是SimpleLayout,RawTimeStampLayout和ExceptionLayout。然后還有IRawLayout,XMLLayout等幾個,使用較少。Layout可以自己實現(xiàn),需要從log4net.Layout.LayoutSkeleton類繼承,來輸出一些特殊需要的格式,在后面擴展時就重新實現(xiàn)了一個Layout。

SimpleLayout簡單輸出格式,只輸出日志級別與消息內(nèi)容。

RawTimeStampLayout?用來格式化時間,在向數(shù)據(jù)庫輸出時會用到。

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

ExceptionLayout需要給Logger的方法傳入Exception對象作為參數(shù)才起作用,否則就什么也不輸出。輸出的時候會包含Message和Trace。

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

3.4 Loggers

Logger是直接和應(yīng)用程序交互的組件。Logger只是產(chǎn)生日志,然后由它引用的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?

高于等級設(shè)定值方法(如何設(shè)置參見“配置文件詳解”)都能寫入日志,?Off所有的寫入方法都不寫到日志里,ALL則相反。例如當(dāng)我們設(shè)成Info時,logger.Debug就會被忽略而不寫入文件,但是FATAL,ERROR,WARN,INFO會被寫入,因為他們等級高于INFO。

在具體寫日志時,一般可以這樣理解日志等級:

FATAL(致命錯誤):記錄系統(tǒng)中出現(xiàn)的能使用系統(tǒng)完全失去功能,服務(wù)停止,系統(tǒng)崩潰等使系統(tǒng)無法繼續(xù)運行下去的錯誤。例如,數(shù)據(jù)庫無法連接,系統(tǒng)出現(xiàn)死循環(huán)。

ERROR(一般錯誤):記錄系統(tǒng)中出現(xiàn)的導(dǎo)致系統(tǒng)不穩(wěn)定,部分功能出現(xiàn)混亂或部分功能失效一類的錯誤。例如,數(shù)據(jù)字段為空,數(shù)據(jù)操作不可完成,操作出現(xiàn)異常等。

WARN(警告):記錄系統(tǒng)中不影響系統(tǒng)繼續(xù)運行,但不符合系統(tǒng)運行正常條件,有可能引起系統(tǒng)錯誤的信息。例如,記錄內(nèi)容為空,數(shù)據(jù)內(nèi)容不正確等。

INFO(一般信息):記錄系統(tǒng)運行中應(yīng)該讓用戶知道的基本信息。例如,服務(wù)開始運行,功能已經(jīng)開戶等。

DEBUG?(調(diào)試信息):記錄系統(tǒng)用于調(diào)試的一切信息,內(nèi)容或者是一些關(guān)鍵數(shù)據(jù)內(nèi)容的輸出。

Logger實現(xiàn)的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靜態(tài)方法,可以獲得配置文件中相應(yīng)的Logger:

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

3.5 Object Renders

它將告訴logger如何把一個對象轉(zhuǎn)化為一個字符串記錄到日志里。(ILog中定義的接口接收的參數(shù)是Object,而不是String。)

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

3.6 Repository

Repository主要用于日志對象組織結(jié)構(gòu)的維護。

4、配置文件詳解

4.1?配置文件構(gòu)成

主要有兩大部分,一是申明一個名為“l(fā)og4net“的自定義配置節(jié),如下所示:

??<configSections>

<section?name="log4net"

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

??</configSections>

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

4.1.1<log4net>

所有的配置都要在<log4net>元素里定義。

支持的屬性:

debug

可選,取值是true或false,默認是false。設(shè)置為true,開啟log4net的內(nèi)部調(diào)試。

update

可選,取值是Merge(合并)或Overwrite(覆蓋),默認值是Merge。設(shè)置為Overwrite,在提交配置的時候會重置已經(jīng)配置過的庫。

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個或多個,?設(shè)置一些參數(shù)。

?

4.1.3?<logger>

支持的屬性:

name

必須的,logger的名稱

additivity

可選,取值是true或false,默認值是true。設(shè)置為false時將阻止父logger中的appender。

支持的子元素:

appender-ref

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

level

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

param

0個或多個,?設(shè)置一些參數(shù)。

?

4.1.4?<appender>

定義日志的輸出方式,只能作為?log4net?的子元素。name屬性必須唯一,type屬性必須指定。

支持的屬性:

name

必須的,Appender對象的名稱

type

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

支持的子元素:

appender-ref

0個或多個,允許此appender引用其他appender,并不是所以appender類型都支持。

filter

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

layout

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

param

0個或多個,?設(shè)置Appender類中對應(yīng)的屬性的值。

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

?

4.1.5?<layout>

布局,只能作為<appender>的子元素。

支持的屬性:

type

必須的,Layout的類型

支持的子元素:

param

0個或多個,?設(shè)置一些參數(shù)。

?

4.1.6?<filter>

過濾器,只能作為<appender>的子元素。

支持的屬性:

type

必須的,Filter的類型

支持的子元素:

param

0個或多個,?設(shè)置一些參數(shù)。

?

4.1.7?<param>

<param>元素可以是任何元素的子元素。

支持的屬性:

name

必須的,取值是父對象的參數(shù)名。

value

可選的,value和type中,必須有一個屬性被指定。value是一個能被轉(zhuǎn)化為參數(shù)值的字符串。

type

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

支持的子元素:

param

0個或多個,?設(shè)置一些參數(shù)。

?

4.2 <appender>配置

???<appender>在配置文件中至少有一個,也可以有多個,有些<appender>類型還可以引用其他<appender>類型,具體參數(shù)可參見上表。

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

4.2.1寫入回滾文件

????<appender?name="ReflectionLayout"?type="log4net.Appender.RollingFileAppender,log4net">

<!--日志文件路徑,“/”與“/”作用相同,到達的目錄相同,文件夾不存在則新建?-->

<!--按文件大小方式輸出時在這里指定文件名,并且當(dāng)天的日志在下一天時在文件名后自動追加當(dāng)天日期形成新文件。-->

<!—按照日期形式輸出時,直接連接元素DatePattern的value形成文件路徑。此處使用這種方式?-->

<!--param的名稱,可以直接查對應(yīng)的appender類的屬性名即可,這里要查的就是RollingFileAppender類的屬性?-->

??????<param?name="File"?value="D:/Log/"?/>

?

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

??????<param?name="AppendToFile"?value="true"?/>

?

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

??????<lockingModel?type="log4net.Appender.FileAppender+MinimalLock"?/>

?

??????<!—使用Unicode編碼-->

??????<Encoding?value="UTF-8"?/>

?

??????<!--最多產(chǎn)生的日志文件數(shù),超過則只保留最新的n個。設(shè)定值value="-1"為不限文件數(shù)-->

??????<param?name="MaxSizeRollBackups"?value="10"?/>

?

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

??????<param?name="StaticLogFileName"?value="false"?/>

?

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

??????<param?name="RollingStyle"?value="Composite"?/>

?

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

<!—此處按日期產(chǎn)生文件夾,文件名固定。注意&quot;?的位置-->

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

<!—這是按日期產(chǎn)生文件夾,并在文件名前也加上日期-->

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

<!—這是先按日期產(chǎn)生文件夾,再形成下一級固定的文件夾—>

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

?

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

超出大小后在所有文件名后自動增加正整數(shù)重新命名,數(shù)字最大的最早寫入。

可用的單位:KB|MB|GB。不要使用小數(shù),否則會一直寫入當(dāng)前日志-->

??????<param?name="maximumFileSize"?value="500KB"?/>

?

<!--計數(shù)類型為1,2,3…-->
??????<param?name="CountDirection"?value="1"/>

?

<!—過濾設(shè)置,LevelRangeFilter為使用的過濾器。?-->

??????<filter?type="log4net.Filter.LevelRangeFilter">

????????<param?name="LevelMin"?value="DEBUG"?/>

????????<param?name="LevelMax"?value="WARN"?/>

??????</filter>

?

??????<!--記錄的格式。一般用log4net.Layout.PatternLayout布局-->

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

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

??????<layout?type="TGLog.ExpandLayout2.ReflectionLayout,TGLog">

????????<param?name="ConversionPattern"

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

??????</layout>

</appender>

注意這些配置屬性有些是可選的,如果需要,一定要寫正確,否則要么輸出的不是自己想要的結(jié)果,要么干脆不輸出任何信息。

4.2.1寫入SQL數(shù)據(jù)庫

需要在相應(yīng)的數(shù)據(jù)庫中準備好一張表,創(chuàng)建語句如下:

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

)

<appender?name="ADONetAppender"?type="log4net.Appender.ADONetAppender,log4net">

<!--BufferSize為緩沖區(qū)大小,只有日志記錄超設(shè)定值才會一塊寫入到數(shù)據(jù)庫-->

<bufferSize?value="10"?/><!—或?qū)憺?lt;param name="BufferSize" value="10" />-->

?

<!--引用-->

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

?

<!--連接數(shù)據(jù)庫字符串-->

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

?

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

<commandText?value="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>

????????<parameterName?value="@log_date"?/>

????????<dbType?value="DateTime"?/>

????????<layout?type="log4net.Layout.RawTimeStampLayout"?/>

??????</parameter>

?

??????<!--線程號-->

??????<parameter>

????????<parameterName?value="@thread"?/>

????????<dbType?value="String"?/>

<!—長度不可以省略,否則不會輸出-->

????????<size?value="100"?/>

????????<layout?type="log4net.Layout.PatternLayout">

??????????<conversionPattern?value="%thread"?/>

????????</layout>

??????</parameter>

?

??????<!--日志等級-->

??????<parameter>

????????<parameterName?value="@log_level"?/>

????????<dbType?value="String"?/>

????????<size?value="100"?/>

????????<layout?type="log4net.Layout.PatternLayout">

??????????<conversionPattern?value="%level"?/>

????????</layout>

??????</parameter>

?

??????<!--日志記錄類名稱-->

??????<parameter>

????????<parameterName?value="@logger"?/>

????????<dbType?value="String"?/>

????????<size?value="200"?/>

????????<layout?type="log4net.Layout.PatternLayout">

??????????<conversionPattern?value="%logger"?/>

????????</layout>

??????</parameter>

?????

??????<!--操作者。這個是自定義的輸出字段,使用重新實現(xiàn)的布局器ReflectionLayout -->

??????<parameter>

????????<parameterName?value="@operator"?/>

<!—設(shè)置為Int32時只有bufferSize的?value<="1"才正確輸出,沒有找出原因。-->

????????<dbType?value="Int16"?/>

????????<layout?type="TGLog.ExpandLayout2.ReflectionLayout,TGLog">

??????????<conversionPattern?value="%property{Operator}"?/>

????????</layout>

??????</parameter>

?

??????<!--操作對象-->

??????<parameter>

????????<parameterName?value="@operand"?/>

????????<dbType?value="String"?/>

????????<size?value="300"?/>

????????<layout?type="TGLog.ExpandLayout2.ReflectionLayout,TGLog">

??????????<conversionPattern?value="%property{Operand}"?/>

????????</layout>

??????</parameter>

?

??????<!—IP地址-->

??????<parameter>

????????<parameterName?value="@ip"?/>

????????<dbType?value="String"?/>

????????<size?value="20"?/>

????????<layout?type="TGLog.ExpandLayout2.ReflectionLayout,TGLog">

??????????<conversionPattern?value="%property{IP}"?/>

????????</layout>

??????</parameter>

?

??????<!--機器名-->

??????<parameter>

????????<parameterName?value="@machineName"?/>

????????<dbType?value="String"?/>

????????<size?value="100"?/>

????????<layout?type="TGLog.ExpandLayout2.ReflectionLayout,TGLog">

??????????<conversionPattern?value="%property{MachineName}"?/>

????????</layout>

??????</parameter>

?

??????<!--瀏覽器-->

??????<parameter>

????????<parameterName?value="@browser"?/>

????????<dbType?value="String"?/>

????????<size?value="50"?/>

????????<layout?type="TGLog.ExpandLayout2.ReflectionLayout,TGLog">

??????????<conversionPattern?value="%property{Browser}"?/>

????????</layout>

??????</parameter>

?????

??????<!—日志消息-->

??????<parameter>

????????<parameterName?value="@message"?/>

????????<dbType?value="String"?/>

????????<size?value="3000"?/>

????????<layout?type="TGLog.ExpandLayout2.ReflectionLayout,TGLog">

??????????<conversionPattern?value="%property{Message}"?/>

????????</layout>

??????</parameter>

?

??????<!--動作類型-->

??????<parameter>

????????<parameterName?value="@action_type"?/>

????????<dbType?value="Int16"?/>

????????<layout?type="TGLog.ExpandLayout2.ReflectionLayout,TGLog">

??????????<conversionPattern?value="%property{ActionType}"?/>

????????</layout>

??????</parameter>

?

??????<!—記錄日志的位置-->

??????<parameter>

????????<parameterName?value="@location"?/>

????????<dbType?value="String"?/>

????????<size?value="2000"?/>

????????<layout?type="log4net.Layout.PatternLayout">

??????????<conversionPattern?value="%location"?/>

????????</layout>

??????</parameter>

?????

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

??????<parameter>

????????<parameterName?value="@exception"?/>

????????<dbType?value="String"?/>

????????<size?value="4000"?/>

????????<layout?type="log4net.Layout.ExceptionLayout"?/>

??????</parameter>

</appender>

注意:

向表中輸出的字段不能多于數(shù)據(jù)表本身字段,而反之則可以,但這些多余字段一定使其可以為空,否則便寫不到數(shù)據(jù)庫;

輸出字段的類型一定是對應(yīng)數(shù)據(jù)表字段數(shù)據(jù)類型可以隱式轉(zhuǎn)換的,而且長度也不能超過,否則也不能寫入;

數(shù)據(jù)表字段設(shè)置盡量可以為空,這樣可以避免一條日志記錄存在空數(shù)據(jù)導(dǎo)致后面的日志都記錄不了。

4.3<logger>的配置

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

在框架的體系里,所有的日志對象都是根日志(root logger)的后代。?因此如果一個日志對象沒有在配置文件里顯式定義,則框架使用根日志中定義的屬性。在<root>標簽里,可以定義level級別值和Appender的列表。如果沒有定義LEVEL的值,則缺省為DEBUG。可以通過<appender-ref>標簽定義日志對象使用的Appender對象。<appender-ref>聲明了在其他地方定義的Appender對象的一個引用。在一個logger對象中的設(shè)置會覆蓋根日志的設(shè)置。而對Appender屬性來說,子日志對象則會繼承父日志對象的Appender列表。這種缺省的行為方式也可以通過顯式地設(shè)定<logger>標簽的additivity屬性為false而改變。

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

<!--同時寫兩個文件和數(shù)據(jù)庫-->

<logger?name="ReflectionLayout">

??????<level?value="DEBUG"/>

??????<appender-ref?ref="HashtableLayout"/>

??????<appender-ref?ref="ReflectionLayout"/>

??????<appender-ref?ref="ADONetAppender"/>

</logger>

4.4關(guān)聯(lián)配置文件

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

log4net.Config.XmlConifguratorAttribute。

?

XmlConfiguratorAttribute有3個屬性:

ConfigFile:?配置文件的名字,文件路徑相對于應(yīng)用程序目錄

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

ConfigFileExtension:?配置文件的擴展名,文件路徑相對于應(yīng)用程序的目錄。ConfigFileExtension屬性不能和ConfigFile屬性一起使用。

Watch:?如果將Watch屬性設(shè)置為true,就會監(jiān)視配置文件。當(dāng)配置文件發(fā)生變化的時候,就會重新加載。

如果ConfigFile和ConfigFileExtension都沒有設(shè)置,則使用應(yīng)用程序的配置文件App.config(Web.config)。

?

可以在項目的AssemblyInfo.cs文件里添加以下的語句:

?//監(jiān)視默認的配置文件,App.exe.config???

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

?

//監(jiān)視配置文件,App.exe.log4net。

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

?

//使用配置文件log4net.config,不監(jiān)視改變。注意log4net.config文件的目錄,BS程序在站點目錄//下,CS則在應(yīng)用程序啟動目錄下,如調(diào)試時在/bin/Debug下,一般將文件屬性的文件輸出目錄調(diào)為//始終復(fù)制即可

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

?

//使用配置文件log4net.config,不監(jiān)視改變

[assembly: log4net. Config.XmlConfigurator()]

?

也可以在Global.asax的Application_Start里或者是Program.cs中的Main方法中添加,注意這里一定是絕對路徑,如下所示:

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

// ConfigureAndWatch()相當(dāng)于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的值。

對應(yīng)5個日志輸出級別,log有5?個方法,每個方法都有兩個重載,使用如下:

try

????????????{

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

????????????}

????????????catch(Exception?ec)

????????????{

????????????????log.Error("出現(xiàn)錯誤!", ec);

?????????}

如果我們需要輸出的消息是要區(qū)別開來,不按一個字符串全部輸出,就需要進行一些擴展了。

6、Log4net的簡單擴展

6.1通過重寫布局Layout輸出傳入的?message對象的屬性

6.1.1重寫Layout類

通過繼承l(wèi)og4net.Layout.PatternLayout類,使用log4net.Core.LoggingEvent類的方法得到了要輸出的message類的名稱,然后通過反射得到各個屬性的值,使用PatternLayout類AddConverter方法傳入得到的值。這里注意要引用用到的類的命名空間。

代碼見附注8.2。

?

6.1.2配置相應(yīng)的配置文件

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

<layout?type="TGLog.ExpandLayout2.ReflectionLayout,TGLog">

????????<param?name="ConversionPattern"

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

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

??????</layout>

其中<layout>的type由原來的log4net.Layout.PatternLayout換為自定義的TGLog.ExpandLayout2.ReflectionLayout(TGLog.ExpandLayout2為命名空間)。%property{Operator}輸出的即為message類對象的屬性O(shè)perator的值。數(shù)據(jù)庫配置同樣,相應(yīng)的字段如果是自定義的,則輸出選用自定義的<layout>。例:

<!--動作類型-->

??<parameter>

??????<parameterName?value="@action_type"?/>

??????<dbType?value="Int16"?/>

??????<layout?type="TGLog.ExpandLayout2.ReflectionLayout,TGLog">

?????????<conversionPattern?value="%property{ActionType}"?/>

??????</layout>

??</parameter>

6.1.3程序中如何使用

和一般使用方法基本相同,只是傳入的參數(shù)是一個自定義的類,類的屬性和配置文件中<layout>所有的%property{屬性}是一致的,即%property{屬性}在輸出的時候就查找傳入message類中有無對應(yīng)的屬性,如果有就輸出值,沒有則輸出null。例:

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

try

????????????{

????????????????log.Debug(new?LogMessage(

1,

"操作對象:0",

?(int)TGLog.ActionType.Other,

?"這是四個參數(shù)測試")

);

????????????}

????????????catch(Exception?ec)

????????????{

????????????????log.Error(new?LogMessage(

????????????????????????????????????1,

????????????????????????????????????"操作對象:0",

????????????????????????????????????(int)TGLog.ActionType.Other,

????????????????????????????????????"這是全部參數(shù)測試",

????????????????????????????????????"192.168.1.1",

????????????????????????????????????"MyComputer",

????????????????????????????????????"Maxthon(MyIE2)Fans"),

?????????????????????????ec

);

??????}

LogMessage的全部屬性的構(gòu)造方法如下:

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通過重新實現(xiàn)ILog接口來增加輸入的參數(shù)

6.2.1重寫LogImpl,LogManager類及實現(xiàn)ILog接口

這種方式是通過構(gòu)造一個名為IMyLog接口,是繼承Ilog接口而來,然后分別在MyLogImpl,MyLogManager重新實現(xiàn)IMyLog接口,增加了每種方法的參數(shù)。MyLogImpl,MyLogManager分別繼承LogImpl,LogManager而來。

代碼分別見8.3、8.4、8.5:

6.2.2配置相應(yīng)的配置文件

配置文件其他地方不用改動,只是需要改動<appender>中的<layout>元素name為ConversionPattern的value中輸出格式。例如:

<layout?type="?log4net.Layout.PatternLayout?">

????????<param?name="ConversionPattern"

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

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

??????</layout>

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

loggingEvent.Properties["Operator"] = operatorID;

就定義了Operator輸出參數(shù),即%property{Operator}輸出的即為IMyLog中的參數(shù)operatorID的值。

數(shù)據(jù)庫配置同樣。例:

<!--動作類型-->

??<parameter>

??????<parameterName?value="@action_type"?/>

??????<dbType?value="Int16"?/>

??????<layout?type="?log4net.Layout.PatternLayout?">

?????????<conversionPattern?value="%property{ActionType}"?/>

??????</layout>

??</parameter>

6.2.3程序中如何使用

先引用IMyLog?,MyLogManager所在的命名空間,創(chuàng)建一個IMyLog對象,myLog的5?個方法,每個方法都有四個重載,增加了多參數(shù)的重載。例:

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

try

????????????{

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

}

????????????catch(Exception?ec)

????????????{

????????????????log.Error(

??????????????????????????1,

??????????????????????????"操作對象:0",

??????????????????????????(int)TGLog.ActionType.Other,

??????????????????????????"這是全部參數(shù)測試",

??????????????????????????"192.168.1.1",

??????????????????????????"MyComputer",

??????????????????????????"Maxthon(MyIE2)Fans",

??????????????????????????ec

);

??????}

7、總結(jié)

Log4net?功能很多,這里只是對已經(jīng)嘗試用過的功能總結(jié)一下,普通寫日志已經(jīng)足夠。需要注意的是:

1.????????????Log4net本身也有一些缺陷,比如一個記錄引起了log4net本身的異常,就會使后面的日志無法記錄下來,尤其是在寫入數(shù)據(jù)庫時。例如使用6.1擴展后,int型的屬性在<appender?>的元素<bufferSize>設(shè)置不為1時,<dbType?value="Int32"?/>時,就不能輸出到數(shù)據(jù)庫,而<dbType?value="Int16"?/>則沒任何問題。

2.????????????Log4net本身出現(xiàn)了異常,比如配置文件出現(xiàn)錯誤,有些日志輸出方式會記錄下這些異常,例如應(yīng)用程序控制臺;有些則不會輸出這些錯誤,如數(shù)據(jù)庫與文件。

3.????????????擴展時也會留下一些問題。例如在使用6.1擴展輸出字段時就會出現(xiàn),在log.debug(object message)中,如果message是一個自定義的類,屬性與配置文件中輸出設(shè)置也一致,構(gòu)造函數(shù)時也只構(gòu)造一個參數(shù)的實例,寫文件與寫數(shù)據(jù)庫都成功,而將message按沒有擴展的方式直接傳入一個字符串,即log.debug(“信息內(nèi)容”)使用則只能寫入文件,而數(shù)據(jù)庫則沒寫入。自定義的Layout?就是繼承默認的PatternLayout,本來不應(yīng)該出錯,但出現(xiàn)了問題。原因分析是自定義的message類有類型為int的屬性,作為一個對象傳入時在默認值0,而直接使用字符串則int型的字段得不到默認值,引發(fā)異常。所以建議在有擴展存在時,最好多設(shè)幾個<logger>,區(qū)分清楚,按照統(tǒng)一的形式記錄日志,不要混合使用。

4.????????????配置文件的設(shè)置一定要準確,在一點不正確就會導(dǎo)致日志不能正常輸出,所以在配置時先從最簡單的開始,同時輸出方式選擇一種能輸出log4net本身異常的方式,成功后一點一點加在新配置,這樣出錯了也容易找到那個地方配置有問題。

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

8、附注:

8.1PatterLayout格式化字符表

轉(zhuǎn)換字符

效果

a

等價于appdomain

appdomain

引發(fā)日志事件的應(yīng)用程序域的友好名稱。(使用中一般是可執(zhí)行文件的名字。)

c

等價于?logger

C

等價于?type

class

等價于?type

d

等價于?date

date

發(fā)生日志事件的本地時間。?使用?DE>%utcdate?輸出UTC時間。date后面還可以跟一個日期格式,用大括號括起來。DE>例如:%date{HH:mm:ss,fff}或者%date{dd MMM yyyy HH:mm:ss,fff}。如果date后面什么也不跟,將使用ISO8601?格式?。

日期格式和.Net中DateTime類的ToString方法中使用的格式是一樣。

另外log4net還有3個自己的格式Formatter。?它們是?"ABSOLUTE", "DATE"和"ISO8601"分別代表?AbsoluteTimeDateFormatter, DateTimeDateFormatter和Iso8601DateFormatter。例如:%date{ISO8601}或%date{ABSOLUTE}。

它們的性能要好于ToString。

exception

異常信息

日志事件中必須存了一個異常對象,如果日志事件不包含沒有異常對象,將什么也不輸出。異常輸出完畢后會跟一個換行。一般會在輸出異常前加一個換行,并將異常放在最后。

F

等價于?file

file

發(fā)生日志請求的源代碼文件的名字。

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

identity

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

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

l

等價于?location

L

等價于?line

location

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

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

level

日志事件等級

line

引發(fā)日志事件的行號

警告:會影響性能。

logger

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

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

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

m

等價于?message

M

等價于?method

message

由應(yīng)用程序提供給日志事件的消息。

mdc

MDC (舊為:ThreadContext.Properties)?現(xiàn)在是事件屬性的一部分。?保留它是為了兼容性,它等價于?property。

method

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

警告:會影響性能。

n

等價于?newline

newline

換行符

ndc

NDC (nested diagnostic context)

p

等價于?level

P

等價于?property

properties

等價于?property

property

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

%property將輸出所有的屬性?。

(擴展后可以使用)

?

r

等價于?timestamp

t

等價于?thread

timestamp

從程序啟動到事件發(fā)生所經(jīng)過的毫秒數(shù)。

thread

引發(fā)日志事件的線程,如果沒有線程名就使用線程號。

type

引發(fā)日志請求的類的全名。.

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

警告:會影響性能。

u

等價于?identity

username

當(dāng)前用戶的WindowsIdentity。(類似:HostName/Username)

警告:會影響性能。

utcdate

發(fā)生日志事件的UTC時間。DE>后面還可以跟一個日期格式,用大括號括起來。DE>例如:%utcdate{HH:mm:ss,fff}或者%utcdate{dd MMM yyyy HH:mm:ss,fff}。如果utcdate后面什么也不跟,將使用ISO8601?格式?。

日期格式和.Net中DateTime類的ToString方法中使用的格式是一樣。

另外log4net還有3個自己的格式Formatter。?它們是?"ABSOLUTE", "DATE"和"ISO8601"分別代表?AbsoluteTimeDateFormatter, DateTimeDateFormatter和Iso8601DateFormatter。例如:%date{ISO8601}或%date{ABSOLUTE}。

它們的性能要好于ToString。

w

等價于?username

x

等價于?ndc

X

等價于?mdc

%

%%輸出一個百分號

關(guān)于調(diào)用本地信息(caller location information)的說明:

%type %file %line %method %location %class %C %F %L %l %M?都會調(diào)用本地信息。這樣做會影響性能。本地信息使用System.Diagnostics.StackTrace得到。.Net 1.0?不支持System.Diagnostics.StackTrace?類。

本地信息在調(diào)試模式下可以正常獲取,在非調(diào)試模式下可能獲取不到,或只能獲取一部分。(根據(jù)我的測試,其實是需要有一個程序數(shù)據(jù)庫(.pdb)文件。)

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

默認屬性log4net:HostName不用設(shè)置。

轉(zhuǎn)義字符的修飾符:

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名要在20到30之間,少了在左邊補空格,多了截斷。

%-20.30logger

true

20

30

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

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

????????????{

????????????????//?寫入所有關(guān)鍵值對

????????????????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(newWrapperCreationHandler(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參考

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

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

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

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

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

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

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

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

?

轉(zhuǎn)載于:https://www.cnblogs.com/hao-1234-1234/p/9065332.html

總結(jié)

以上是生活随笔為你收集整理的非常完善的Log4net详细说明(转)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

正在播放国产一区二区 | 97精品国产91久久久久久 | 久久黄色免费 | 欧美色一色 | 蜜臀久久99精品久久久久久网站 | 欧美一区,二区 | 亚洲国产激情 | 黄色软件在线观看免费 | 国产精品女人久久久久久 | 亚洲精品久久久久中文字幕二区 | 五月天天天操 | 天天草天天干天天射 | 国产一级不卡视频 | 一区二区三区日韩视频在线观看 | 国产精品去看片 | 91香蕉视频在线 | 黄色1级大片| 国产无套精品久久久久久 | 亚欧日韩av | 91麻豆精品国产91 | 99re8这里有精品热视频免费 | 色网站在线 | 成人国产精品电影 | 天天操天天艹 | 久久久2o19精品 | 色妞久久福利网 | av在线永久免费观看 | 国产一二区视频 | 97理论电影| 久草视频免费播放 | 在线观看免费av网 | 日本少妇高清做爰视频 | 亚洲一区日韩 | av手机在线播放 | 美女视频黄色免费 | 午夜精品久久久久久久99热影院 | 日韩在线色 | www.色午夜.com | 亚洲欧美精品一区 | 成 人 黄 色 视频免费播放 | 99久久99久久 | 天天曰 | 视频成人 | 精品影院一区二区久久久 | 中日韩在线视频 | 又爽又黄在线观看 | 五月婷婷综合激情网 | 一区二区三区久久 | 97人人射 | 久久少妇免费视频 | 99久免费精品视频在线观看 | 四虎在线影视 | 婷婷丁香狠狠爱 | 国产精品原创视频 | 国产亚洲成av片在线观看 | 少妇视频一区 | 黄色h在线观看 | 九九视频这里只有精品 | 国产小视频网站 | 91中文在线视频 | 玖玖在线精品 | 久久久免费精品视频 | 亚洲精品国产精品乱码不99热 | 日韩免费成人av | 在线观看麻豆av | 伊人天堂久久 | 久久久亚洲成人 | 欧美日韩国产亚洲乱码字幕 | 国产91在线观 | 国产精品1区2区在线观看 | 精品一区 精品二区 | 九热在线 | 国产色一区| 精品视频久久 | 欧美一级性生活片 | 色偷偷88欧美精品久久久 | 岛国av在线不卡 | 2019中文最近的2019中文在线 | 亚洲视频免费在线看 | 日韩欧美在线观看一区二区 | 免费日韩一级片 | 久久不射影院 | 日韩在线视频免费看 | 亚洲国产人午在线一二区 | 99免费在线观看视频 | 免费观看高清 | 国产91粉嫩白浆在线观看 | 成片免费观看视频999 | 久久草在线免费 | 天天搞天天干天天色 | 欧美黄色免费 | 色com网 | 日韩xxx视频 | 久久国产手机看片 | 婷婷成人亚洲综合国产xv88 | 中文字幕在线观看一区二区 | 国产免费不卡av | 国内一级片在线观看 | 国产亚洲精品久久久久久大师 | 美女黄视频免费看 | 在线看v片成人 | 日韩在线视频观看免费 | 国产成人精品av久久 | 色婷av| 中文字幕韩在线第一页 | 国产精品久久久久久久av大片 | 九九九热精品 | 亚洲在线视频免费观看 | 欧美精品视 | 成人午夜电影在线播放 | 久草在线在线精品观看 | 欧美一级片在线观看视频 | 97香蕉久久国产在线观看 | 亚洲激情综合网 | 国产五月天婷婷 | 在线观看视频国产一区 | 久久久久久久久久久久久影院 | 在线观看亚洲成人 | 欧美日韩精品影院 | 操处女逼 | 在线观看av麻豆 | 99久久精品费精品 | 欧美孕交vivoestv另类 | 蜜臀av夜夜澡人人爽人人 | 中文字幕日韩电影 | 免费久久久| 欧美精品乱码99久久影院 | 国产精品久久久久久99 | 亚洲国产中文字幕 | 99综合电影在线视频 | 亚洲人成在线观看 | 色哟哟国产精品 | 亚洲国产精品人久久电影 | 国产精品久久久免费看 | 午夜私人影院久久久久 | 91av中文| 精品亚洲成人 | 91探花系列在线播放 | 亚洲精品乱码久久久久久蜜桃不爽 | 日本一区二区不卡高清 | 国产精品久久久久久一区二区三区 | 中文字幕高清 | 亚洲精品www. | 91传媒免费观看 | 久久五月天婷婷 | 四虎影视8848dvd | 国产在线观看中文字幕 | 精品国产99国产精品 | 久久人人添人人爽添人人88v | 精品国产福利在线 | 欧美国产日韩一区 | 久久久久久久久久国产精品 | 亚洲在线资源 | 一区在线观看 | 久久久不卡影院 | 91精品国产91久久久久 | 亚洲四虎| 日日夜夜狠狠操 | 一级黄色片在线播放 | 亚洲va在线va天堂 | 在线观看日韩中文字幕 | 国产日韩亚洲 | 成人av电影免费在线观看 | 久久免费一 | av在线精品 | 欧美综合在线视频 | 国产精品福利无圣光在线一区 | 99热这里只有精品久久 | 国产成人免费观看久久久 | 国产99亚洲 | 免费亚洲黄色 | 久久久www成人免费精品 | 天天在线操 | 欧美一区二区免费在线观看 | 精品国产一区二区三区在线 | 又色又爽又激情的59视频 | 亚洲国内精品视频 | www.神马久久 | 视频在线观看国产 | 午夜av免费观看 | 激情婷婷| 在线视频 一区二区 | 国产一区在线播放 | 国语自产偷拍精品视频偷 | 国产成人香蕉 | 99在线免费观看视频 | 黄av免费在线观看 | 天天干天天操天天拍 | 波多野结衣亚洲一区二区 | 亚洲精品视频在线免费 | 午夜色影院 | 日本黄色片一区二区 | 久久蜜桃av | 97精品国产97久久久久久粉红 | 久久精品8 | 手机在线视频福利 | 欧美日韩另类在线 | 热久在线 | 四虎影视久久久 | 久久综合五月天 | 日本黄色大片免费看 | av中文字幕在线看 | 欧美日韩国产综合一区二区 | 国产xxxxx在线观看 | www.久草.com | 久久久久久久网站 | 97超碰在线久草超碰在线观看 | 毛片在线网| 成人在线你懂得 | 免费成人短视频 | 国产一级做a | 国产中文字幕大全 | 开心激情综合网 | 中文国产字幕 | 日本在线观看一区 | 欧美精品在线观看一区 | 五月天激情综合网 | 欧美日韩亚洲在线观看 | 精品视频免费在线 | 国产综合在线观看视频 | 日本久久成人 | 国产午夜三级一区二区三 | 99在线观看视频网站 | 日韩精品免费一区 | 在线观看精品一区 | 成+人+色综合 | 超碰在线人人艹 | 日韩在线视频免费播放 | 黄色在线小网站 | 亚洲 中文字幕av | 欧美日韩视频在线观看免费 | 欧美日韩不卡在线视频 | 97超碰站| 欧美精品在线一区二区 | 美女av电影 | 伊人永久 | 亚洲视频免费在线 | 99国产情侣在线播放 | 亚洲精品视频免费在线 | 久久精品精品 | 99久久夜色精品国产亚洲 | 在线激情av电影 | 国产99在线| 欧美性久久久久久 | 日本精品久久 | 亚洲视频播放 | 91在线欧美| 玖玖玖在线 | 五月婷网站 | 免费在线91| 国产精品免费久久久久久 | 天天爱天天色 | 最新久久免费视频 | 亚洲精品ww | 国产中文字幕大全 | 99精品视频在线观看视频 | 国产精品粉嫩 | 欧美精品久久久久久久久免 | 亚洲成年片 | 婷婷六月天在线 | 午夜久久影视 | 日本中文字幕网站 | 在线观看网站黄 | 国产一区二区精品在线 | 在线观看成人网 | 91视频高清完整版 | 国产精品麻豆一区二区三区 | 99中文在线| 美女网站视频色 | 97在线观看免费观看高清 | 91av在线免费播放 | 免费成人av在线看 | 国产精品第一页在线观看 | 久草精品视频 | 在线观看色视频 | 不卡视频国产 | 国产精品不卡一区 | 色网站在线免费 | 国产三级午夜理伦三级 | 久久成年人网站 | 中文字幕在线高清 | 亚洲成a人片综合在线 | 男女拍拍免费视频 | 九九99| 精品久久久久久久久久久久久 | 中文视频在线看 | 国产一区二区三区免费观看视频 | 久久久久久国产精品免费 | 国产午夜激情视频 | 91久久精品一区二区二区 | 久久国产视屏 | 国产精品久久久久久超碰 | 成人一区二区三区中文字幕 | 色在线观看网站 | 免费美女av| 国产高清视频免费观看 | 国产精品视频 | 人人澡超碰碰 | 天堂网在线视频 | 99精品热视频只有精品10 | 国模精品一区二区三区 | 99色99| 在线不卡的av | 正在播放五月婷婷狠狠干 | 久久高清国产 | 久久毛片高清国产 | 91成人观看 | 99久久精品免费看国产一区二区三区 | 欧美另类交在线观看 | 精品一区二区免费视频 | 免费在线观看污 | 精品国内自产拍在线观看视频 | 国产亚洲精品久久久久久无几年桃 | 色橹橹欧美在线观看视频高清 | 国产精品入口麻豆www | 久草在线费播放视频 | 国产不卡精品视频 | 欧美日本三级 | 欧美福利久久 | 久久精品亚洲精品国产欧美 | 亚洲午夜精 | 狠狠色2019综合网 | 天天干天天操天天做 | 欧美日韩视频免费看 | 国产精品区二区三区日本 | 日日夜夜草 | 操高跟美女| 国产91九色视频 | 国产精品久久久久久久久毛片 | 亚洲国产97在线精品一区 | 久久久久久久久久久免费视频 | 黄色免费大片 | 婷婷综合激情 | 日韩欧美一区二区在线播放 | 欧美最新大片在线看 | 国产专区欧美专区 | 久久久久久久久电影 | 在线免费观看一区二区三区 | 国产亚洲一区二区在线观看 | 中文字幕视频观看 | 人人舔人人舔 | 日日夜夜天天 | 少妇bbbb| 国产69久久久 | 国产99视频在线观看 | 伊人www22综合色 | 久久福利小视频 | 中文字幕免费高清 | 在线精品视频免费观看 | 99国产精品免费网站 | 久草视频免费播放 | 国产美女精品人人做人人爽 | 久久69精品 | 伊甸园av在线| 欧美激情一区不卡 | 亚洲精品视频免费在线 | 福利视频一区二区 | 久草精品免费 | 男女啪啪免费网站 | 欧美一级性生活视频 | av亚洲产国偷v产偷v自拍小说 | 在线观看中文字幕av | 99精品在线视频观看 | 99久久久国产精品美女 | 操操操操网 | 国产精品久久久久久五月尺 | 99视频在线观看免费 | 热久久影视 | 久久久久电影 | 国产手机视频在线播放 | 久久情侣偷拍 | 91在线视频在线 | 欧美久久久久久久久久久久 | 色av婷婷| 日韩在线观看小视频 | 国产乱视频 | 久久国产精品久久久久 | 日韩免费看片 | 在线国产中文字幕 | 日韩最新在线视频 | 激情久久五月 | 日日干天天操 | 中文av一区二区 | 超级碰碰碰免费视频 | 丝袜av网站| 日韩精品一区二区在线视频 | 国产精品自产拍在线观看 | 免费看一级| 99国产精品免费网站 | 97超碰在线久草超碰在线观看 | 欧美激情另类 | 久久视频| 1024在线看片 | 91日本在线播放 | 亚洲资源在线 | japanesefreesex中国少妇 | 婷婷射五月 | 久久99视频精品 | 欧美疯狂性受xxxxx另类 | 黄影院| 亚洲区精品视频 | 99视频在线精品国自产拍免费观看 | 在线香蕉视频 | 欧洲亚洲女同hd | 欧美日本不卡视频 | 国产精品免费一区二区三区 | 亚洲黄色一级大片 | 久久精品视频网址 | 国产欧美综合视频 | 中文字幕在线观看网 | 国产在线高清 | 国产主播大尺度精品福利免费 | 亚洲成人麻豆 | 亚洲专区在线播放 | 九九九热 | 欧美精品久 | 99爱爱| 麻豆91精品 | 999久久精品| 亚洲精品国偷自产在线99热 | 最近免费中文字幕 | 91试看| av观看网站| 欧美视频在线观看免费网址 | 亚洲精品国偷拍自产在线观看蜜桃 | 97天堂| 高清不卡一区二区三区 | 四虎4hu永久免费 | 51久久成人国产精品麻豆 | 久久最新 | 国产精品久久久久久久久蜜臀 | 麻豆视频入口 | 亚洲第一区在线播放 | 久久九九网站 | 日韩av在线影视 | 久久综合视频网 | 国产精品av免费在线观看 | 中文字幕在线影院 | 久艹视频在线免费观看 | 免费av看片 | 在线观看的av | 免费看国产视频 | 成人av在线影视 | 91成人欧美 | 欧美激情片在线观看 | 最新日韩视频 | 91丨九色丨国产丨porny精品 | 国产91精品看黄网站在线观看动漫 | 99精品国产一区二区三区麻豆 | 不卡的av在线 | 成 人 a v天堂 | 亚洲综合欧美激情 | 99色在线视频 | 日色在线视频 | 国产毛片久久久 | 亚洲狠狠操 | 久久小视频| 国产日韩视频在线播放 | 9久久精品 | 在线观看电影av | 在线播放av网址 | 操操操天天操 | 五月婷婷.com | 精品人人人 | 久久久人| 欧美巨乳网 | 一级黄色片在线观看 | 国产特级毛片aaaaaaa高清 | 国产一卡久久电影永久 | 色综合久久综合中文综合网 | www激情com | 香蕉在线影院 | 久久久免费毛片 | 国产黄免费看 | jizz999| 在线欧美中文字幕 | 夜夜躁狠狠躁日日躁视频黑人 | 最新色站| av观看久久久 | 成人影片在线免费观看 | 中文乱码视频在线观看 | 中文字幕视频在线播放 | 久久久一本精品99久久精品 | 一区二区三区电影在线播 | 91视频电影 | 国产视频九色蝌蚪 | 悠悠av资源片 | 久久久久激情 | 五月激情丁香图片 | 美女网站在线 | 99精品在线视频播放 | 91视频网址入口 | 最近能播放的中文字幕 | 激情五月看片 | 在线性视频日韩欧美 | av福利在线免费观看 | 中文字幕区 | 色综合婷婷 | 国产成人精品区 | 久久精品三 | 久久亚洲福利视频 | 国产免费黄色 | 日韩精品不卡在线 | 中文字幕乱偷在线 | 亚洲国产午夜视频 | 久久99久久99| 亚洲国产精品资源 | 五月婷在线播放 | 精品久久久久久亚洲综合网 | 午夜国产在线观看 | 福利电影一区二区 | 国产精品麻豆果冻传媒在线播放 | 亚洲精品中文字幕在线 | 91精品对白一区国产伦 | 久久歪歪 | 一区二区精品视频 | 国产99久久九九精品免费 | 久久免费福利视频 | 九九热国产视频 | 中文字幕一区二区三区四区久久 | 天天干亚洲 | 99精品国产99久久久久久福利 | 日韩网站在线 | 激情五月婷婷激情 | 免费日韩在线 | 国产第一页福利影院 | 久久久男人的天堂 | 欧美日韩精品免费观看视频 | wwwww.国产| 国产98色在线 | 日韩 | 日韩午夜在线播放 | 在线欧美最极品的av | 日本特黄一级片 | 亚州人成在线播放 | 欧美少妇xxx | 天天摸天天操天天爽 | 在线视频一二三 | 日本午夜免费福利视频 | 欧美视频国产视频 | 最新一区二区三区 | 九九九电影免费看 | 国产无遮挡猛进猛出免费软件 | 欧美日韩不卡在线观看 | 日韩试看 | 99久久久久久久久久 | 97电影手机版 | 国产97免费| 成年人视频在线免费播放 | 成片免费| 中文字幕电影高清在线观看 | 正在播放五月婷婷狠狠干 | 黄色成人av网址 | 亚洲精品视频在线免费播放 | 色在线中文字幕 | 精品五月天 | 激情欧美一区二区三区 | 亚洲久草网 | 久草在线资源观看 | 久久美女高清视频 | 亚洲精品视频网 | 91黄视频在线| 国产3p视频 | 精品国产亚洲日本 | 婷婷精品在线视频 | 久久久精品国产免费观看同学 | 播五月综合 | 人人澡人人干 | 中文字幕美女免费在线 | 久久婷五月 | 成人三级网址 | 天天射天天爱天天干 | 精品视频免费 | 亚洲成人精品久久久 | 成年人电影免费看 | 草久草久 | 国产涩图 | 91人网站| 亚洲视频1区2区 | 欧美日韩国产精品爽爽 | 久久国产一区二区 | 在线播放日韩av | 天天插天天色 | 伊人热| 国产欧美精品一区二区三区 | 日本黄区免费视频观看 | 国产精品av在线 | 高潮久久久 | 国产在线观看中文字幕 | 久久精品5 | 美女网站在线 | 久久综合日 | 日韩免费在线观看视频 | 久久一区二区三区日韩 | 久久久久久综合 | 菠萝菠萝在线精品视频 | 亚洲欧美经典 | 国产成人三级一区二区在线观看一 | 九九免费精品视频在线观看 | 日韩视频在线观看免费 | 久久久国产一区 | 国产精品99久久久久久有的能看 | 嫩模bbw搡bbbb搡bbbb | 一区二区 久久 | 久久久国产日韩 | 天天摸天天操天天舔 | 天天干天天操天天入 | 亚洲四虎影院 | 久久久久久久久久亚洲精品 | 亚洲视频久久 | 亚洲成人999 | 草莓视频在线观看免费观看 | 久久99国产精品视频 | 狠狠干狠狠插 | 国产精品国产三级国产 | 欧美成人猛片 | 日韩精品一卡 | 久草在线免费看视频 | 精品亚洲va在线va天堂资源站 | www国产亚洲 | 国产精品亚 | 九色福利视频 | 国产无套精品久久久久久 | 精品二区久久 | 国产区av在线| 国产一区二三区好的 | 狠狠色免费 | av高清一区 | 亚洲传媒在线 | 久久男女视频 | 久久久黄色免费网站 | 久久精品视频4 | 激情婷婷欧美 | 婷婷色在线资源 | 久久99精品久久久久久三级 | 国产精品18久久久久久久久 | 国产成人99久久亚洲综合精品 | 国产精品美女久久久久久2018 | 国产91丝袜在线播放动漫 | 黄色网免费 | 在线免费观看亚洲视频 | 色婷婷狠狠五月综合天色拍 | 欧美日韩国产精品一区二区 | 亚洲精品欧美成人 | 韩国av电影在线观看 | 国产黄a三级三级三级三级三级 | 午夜三级福利 | 亚洲影视资源 | 在线精品视频在线观看高清 | 黄色毛片一级片 | 91av亚洲 | 香蕉在线播放 | 婷婷丁香狠狠爱 | 超碰av在线 | 瑞典xxxx性hd极品 | 激情综合五月天 | 91精品国产自产在线观看 | 久久久久观看 | 91麻豆精品国产91久久久使用方法 | 国产手机视频在线播放 | 国产麻豆剧果冻传媒视频播放量 | 国产黄网在线 | 97在线观看视频国产 | 日韩三级精品 | 综合网天天射 | 精品产品国产在线不卡 | 欧美精品二 | 久久免费在线观看 | 日日夜夜操操操操 | 久久不见久久见免费影院 | 激情婷婷亚洲 | 青青看片| 国产精品久久久久久久久费观看 | 丁香六月婷婷综合 | 久久国产欧美日韩 | 久久 亚洲视频 | 最新一区二区三区 | 色七七亚洲影院 | 激情网站免费观看 | 制服丝袜在线 | 一区二区影院 | 免费日韩一级片 | 99爱在线观看 | 免费观看黄色av | 国产aaa免费视频 | 日日干网| 96在线| 激情婷婷av | 精品国产乱码久久久久久1区2匹 | 国产在线999 | 久久高清毛片 | 成人午夜精品久久久久久久3d | 亚洲少妇自拍 | 色91av | www久 | 久草视频免费 | 精品福利视频在线观看 | 九九久久视频 | 久草免费在线视频 | 天天操天天射天天插 | 黄色影院在线免费观看 | 国产色一区 | 欧美在线观看视频一区二区三区 | 天天操夜夜干 | 久久亚洲私人国产精品 | 亚洲精品动漫久久久久 | 欧美激情精品久久久久久免费印度 | 97人人模人人爽人人少妇 | 66av99精品福利视频在线 | 麻豆影视在线免费观看 | 中日韩男男gay无套 日韩精品一区二区三区高清免费 | 玖玖色在线观看 | 欧美精品在线观看免费 | 超碰夜夜 | 国产香蕉av | 亚洲国产精品电影 | av超碰在线 | 日日干天天射 | 91视频在线观看大全 | 免费观看www小视频的软件 | 人人舔人人射 | 色播激情五月 | 久久精品99久久久久久 | 一级成人免费视频 | 午夜国产福利视频 | 国产在线传媒 | 国产精品av电影 | 奇米影视777四色米奇影院 | 三级动态视频在线观看 | 国产色婷婷精品综合在线手机播放 | 91欧美日韩国产 | 91丨九色丨国产在线 | 91中文字幕在线 | 国产精品毛片网 | 日韩精品中文字幕一区二区 | 欧美精品久久久久久久久久白贞 | 美国av大片 | 日韩免费播放 | 久久成人一区 | av在线播放国产 | av成人黄色| 三级黄色片在线观看 | 婷婷久月 | 丝袜+亚洲+另类+欧美+变态 | 在线视频 一区二区 | 精品一区 精品二区 | av一级在线 | 玖玖视频 | 99在线看 | 婷婷在线网站 | 91视频久久 | 亚州精品视频 | 黄色网www | 97超级碰碰碰碰久久久久 | 国产伦精品一区二区三区在线 | 亚洲h色精品 | 亚洲精品九九 | 成人电影毛片 | 亚洲成人软件 | 亚洲国产中文在线 | 久久99国产视频 | 亚洲激情六月 | 超碰在线人 | 国产精品麻豆免费版 | 国产中文字幕视频 | 国产亚洲精品久久久久久大师 | 中文字幕888 | 久草在线资源免费 | 亚洲麻豆精品 | 亚州黄色一级 | 在线观看成人av | 国产在线不卡一区 | 五月婷婷毛片 | 69国产盗摄一区二区三区五区 | 精品亚洲免费 | 日日草av| 国产va在线| 一区二区三区影院 | 亚洲伦理一区 | 国产成人久久 | 久久久影院| 黄色美女免费网站 | 日韩高清在线一区二区三区 | 激情在线五月天 | 国产精品美女久久久久久久久 | 久久人人爽 | 美女视频久久 | 亚洲 欧美 国产 va在线影院 | 蜜桃视频在线观看一区 | 在线成人免费电影 | 在线a亚洲视频播放在线观看 | 99视频一区二区 | 国产精品九九久久99视频 | 日韩精品视频久久 | 国产在线一区二区三区播放 | 91av视频导航 | www.亚洲| 五月婷婷色综合 | av资源免费在线观看 | 色在线网站| 又黄又爽的视频在线观看网站 | www.狠狠操.com| 高清免费在线视频 | av黄色av | 99精品久久只有精品 | 中文字幕高清视频 | 园产精品久久久久久久7电影 | 999久久国精品免费观看网站 | 久久伊人综合 | av丝袜天堂 | 成人一级电影在线观看 | 国内久久精品 | 亚洲黄色区 | 天天天天天天天操 | 99免在线观看免费视频高清 | 久久成人精品视频 | 97网| 久久免费视频一区 | 91九色在线播放 | 精品久久久久久久久久久久久久久久 | 日韩特黄一级欧美毛片特黄 | 国产精品剧情 | 久久国产网 | 久久午夜免费视频 | 91色偷偷 | 美女视频国产 | 丁香综合网 | 中文字幕在线观 | 国产一区二区久久 | 一区二区精品在线 | 在线国产欧美 | 欧美资源| www色综合 | 日韩精品高清视频 | 黄色三级网站 | 亚洲成人av电影在线 | 国产成人在线免费观看 | 欧美一级久久 | 久久婷婷色 | 欧美午夜寂寞影院 | 色九九在线 | 久久综合欧美精品亚洲一区 | 欧美精彩视频 | 伊人久久国产精品 | 久久视频在线观看 | 欧美性做爰猛烈叫床潮 | 在线色视频小说 | 最近中文字幕mv免费高清在线 | 伊人国产在线观看 | 久久久久久久毛片 | 久久久午夜视频 | 国产成人精品电影久久久 | 欧美国产精品久久久久久免费 | 岛国大片免费视频 | 91麻豆精品国产 | av色网站| 视频一区在线免费观看 | 国产精品视屏 | 精品女同一区二区三区在线观看 | 五月天色网站 | 色多多污污在线观看 | 色网站免费在线看 | 欧美va天堂va视频va在线 | 丰满少妇高潮在线观看 | 91大神电影| 国产91精品一区二区麻豆亚洲 | 中文字幕在线免费观看 | www.久久久com | 九色91av | 国产精品6 | 精品嫩模福利一区二区蜜臀 | 91在线视频网址 | 国产精品视频观看 | www久| 国产精品一区二区三区四区在线观看 | 久久久久久免费 | 色婷婷欧美 | 97人人添人澡人人爽超碰动图 | 天天草天天摸 | 99久久精品费精品 | 国产99在线播放 | 久久精品成人热国产成 | 国产视频一 | 亚洲欧美日本一区二区三区 | 黄色一级在线观看 | 亚洲精品国产成人 | www久久国产 | 手机色在线 | 亚洲成人xxx| 蜜桃av人人夜夜澡人人爽 | 黄色毛片一级片 | 国产91精品一区二区绿帽 | 久久99国产视频 | 免费观看91 | 五月激情在线 | 日韩av在线高清 | 97久久精品午夜一区二区 | 超碰最新网址 | 国产高清在线观看 | 手机色在线 | 国产五码一区 | 免费看片日韩 | 五月开心六月伊人色婷婷 | 四虎天堂| 一区二区欧美激情 | 日本特黄特色aaa大片免费 | 国产拍揄自揄精品视频麻豆 | 亚洲视频播放 | 久久久久观看 | 亚洲精品中文在线 | 成人啪啪18免费游戏链接 | 午夜精品在线看 | 免费国产ww | 国产日韩欧美在线播放 | 免费av在线网 | 欧美大片mv免费 | 在线免费观看黄色大片 | 亚洲精品在线观看中文字幕 | 中文字幕在线观看免费高清完整版 | 久热超碰 | 在线免费视频a | 亚洲精品在线观看网站 | 一区二区激情视频 | 欧美日韩免费看 | 国产精品毛片一区二区三区 | 久久网站免费 | 国产淫片| 欧美动漫一区二区三区 | 亚洲成aⅴ人片久久青草影院 | 精品国产伦一区二区三区观看方式 | 久精品在线观看 | 亚洲国产精品小视频 | 99日韩精品 | 深夜视频久久 | 久久精品牌麻豆国产大山 | 亚洲成人av片 | 狠狠干美女 | 久久69精品 | 日韩在线不卡 | 综合色婷婷 | 久久精久久精 | 久久久片 | 人人澡超碰碰97碰碰碰软件 | 欧美日韩三区二区 | 国产精品12345 | 天天操天天操天天操天天操天天操天天操 | 午夜在线观看影院 | 欧美日韩一区二区在线观看 | 国产精品美女久久久免费 | 91在线精品秘密一区二区 | 中文字幕视频一区 | 国产一区二区影院 | 中文字幕乱码日本亚洲一区二区 | 国产高清av免费在线观看 | 免费在线观看污网站 | 在线观看亚洲国产 | 欧美另类xxx | 精品国产免费久久 | 国产亚洲人成网站在线观看 | 欧美成人区 | 91爱爱电影 | 五月天综合网站 | 久久免费视频2 | 五月香婷| 久草在线官网 | 黄色片软件网站 | 婷婷成人在线 | 国产精品久久久久久久久久东京 | 国产一区二区三区在线 | 字幕网资源站中文字幕 | 国模一区二区三区四区 | 777奇米四色 | 成人精品视频 | 中文字幕欧美日韩va免费视频 | 99热精品久久 | 超碰在线97免费 | 欧美黑人性爽 | 亚洲日本va午夜在线影院 | 97超碰总站 | 成年人网站免费观看 | 四虎在线视频 | 国产精选视频 | 天天搞天天干天天色 | 91av在| 在线а√天堂中文官网 | 亚洲在线视频观看 | av在线播放免费 | av大片免费 | 欧美精品乱码99久久影院 | 久视频在线 | 免费色视频网址 | 91av电影在线观看 | 中文字幕在线网 | 久久久91精品国产一区二区三区 | 精品久久久久久电影 | 国产精品久久久久久久久久ktv | 麻豆精品国产传媒 | 久草免费福利在线观看 | 久久狠狠一本精品综合网 |