一、log4net簡介:
1. Log4net的優點:
幾乎所有的大型應用都會有自己的用於跟蹤調試的API。因為一旦程序被部署以后,就不太可能再利用專門的調試工具了。然而一個管理員可能需要有一套強大的日志系統來診斷和修復配置上的問題。
經驗表明,日志記錄往往是軟件開發周期中的重要組成部分。它具有以下幾個優點:它可以提供應用程序運行時的精確環境,可供開發人員盡快找到應用程序中的Bug;一旦在程序中加入了Log 輸出代碼,程序運行過程中就能生成並輸出日志信息而無需人工干預。另外,日志信息可以輸出到不同的地方(控制台,文件等)以備以后研究之用。
Log4net就是為這樣一個目的設計的,用於.NET開發環境的日志記錄包。
2. Log4net的安裝:
用戶可以從http://logging.apache.org/log4net/下載log4net的源代碼。解壓軟件包后,在解壓的src目錄下將log4net.sln載入Visual Studio .NET,編譯后可以得到log4net.dll。用戶要在自己的程序里加入日志功能,只需將log4net.dll引入工程即可。
3. Log4net的結構
log4net 有四種主要的組件,分別是Logger(記錄器), Repository(庫), Appender(附着器)以及 Layout(布局).
二、log4net使用:
1.創建項目 -> 引入log4net.dll -> 添加文件夾命名為Config -> 添加配置文件命名為log4net.config
2.編輯log4net.config
<?xml version="1.0" encoding="utf-8" ?> <configuration> <!--注冊log4net(目前注釋掉也可以正常使用)--> <!--<configSections> <section name="log4net" type="log4net.Config.IgnoreSectionHandler"/> </configSections>--> <log4net> <!-- 日志默認值節點 --> <root> <!-- 默認日志對象級別 --> <!--(高) OFF > FATAL > ERROR > WARN > INFO > DEBUG > ALL (低) --> <level value="all" /> <!-- 默認日志記錄方式 ref為<appender>節點的name屬性--> <appender-ref ref="MyColoredConsoleAppender"/> <!--<appender-ref ref="MyRollingFileAppender"/>--> </root> <!-- 注意!!! <root>節點和<logger>節點,如果同時出現, 會先執行root的內容,再執行logger的內容, 有可能會出現重復插入記錄的情況, 解決方案:默認節點不設置默認記錄方式 --> <!-- 指定類別日志設置節點 name為LogManager.GetLogger("logger.db.debug")中的name參數 --> <logger name="logger.db.debug"> <!-- 該日志對象的級別(可多個級別設置在一起,公用同一個記錄方式)--> <level value="DEBUG"/> <!-- 該日志對象的記錄方式(可多個記錄方式設置在一起,同時記錄到多種媒介上) --> <appender-ref ref="AdoNetAppender_Debug"/> </logger> <logger name="logger.db.info"> <level value="INFO"/> <appender-ref ref="AdoNetAppender_Info"/> </logger> <!-- 文本日志 --> <logger name="logger.file.debug"> <level value="DEBUG"/> <appender-ref ref="RollingFileAppender_Debug"/> </logger> <logger name="logger.file.other"> <level value="INFO"/> <level value="WARN"/> <appender-ref ref="RollingFileAppender_Other"/> </logger> <!-- AdoNetAppender:利用ADO.NET記錄到數據庫的日志。 ConsoleAppender:將日志輸出到控制台。 RollingFileAppender:將日志以回滾文件(重復操作原始文件)的形式寫到文件中。 --> <!-- 控制台顯示日志 --> <appender name="MyColoredConsoleAppender" type="log4net.Appender.ColoredConsoleAppender"> <!-- 設置不同級別控制台顯示的不同顏色 --> <mapping> <level value="INFO" /> <foreColor value="Green" /> </mapping> <mapping> <level value="ERROR" /> <foreColor value="Red, HighIntensity" /> </mapping> <!-- 記錄的格式。 --> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="%date{HH:mm:ss,fff} [%-5level] %m %n" /> </layout> <!-- 過濾器type有如下幾種類型 log4net.Filter.DenyAllFilter 丟棄所有日志事件。 log4net.Filter.LevelMatchFilter 准確匹配事件等級。 log4net.Filter.LevelRangeFilter 匹配一個范圍的等級。 log4net.Filter.LoggerMatchFilter 匹配一個日志器名字的開始。 log4net.Filter.PropertyFilter 匹配指定屬性名稱的子字符串。 log4net.Filter.StringMatchFilter 匹配事件消息的子字符串。 --> <filter type="log4net.Filter.LevelRangeFilter"> <!-- 控制輸出日志的級別范圍 --> <param name="LevelMin" value="Info" /> <param name="LevelMax" value="Error" /> </filter> </appender> <!-- 文件形式記錄日志-Debug --> <appender name="RollingFileAppender_Debug" type="log4net.Appender.RollingFileAppender"> <!--日志文件路徑,按文件大小方式輸出時在這里指定文件名,並且前面的日志按天在文件名后自動添加當天日期形成文件--> <param name= "File" value= "D:\App_Log\Debug\"/> <!--是否是向文件中追加日志--> <param name= "AppendToFile" value= "true"/> <!--記錄日志寫入文件時,不鎖定文本文件--> <!--<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />--> <!--Unicode編碼--> <!--<Encoding value="UTF-8" />--> <!--最多產生的日志文件數,value="-1"為不限文件數--> <!--<param name="MaxSizeRollBackups" value="10" />--> <!--log保留天數--> <param name= "MaxSizeRollBackups" value= "10"/> <!--日志文件名是否是固定不變的(是否只寫到一個文件中)--> <param name= "StaticLogFileName" value= "false"/> <!--按日期產生文件夾,文件名[在日期方式與混合方式下使用]日志文件名格式為:2008-08-31.log --> <param name= "DatePattern" value= "yyyy-MM-dd".log""/> <!--<param name="DatePattern" value="yyyy-MM-dd/"-ReflectionLayout.log="""" /> <param name="DatePattern" value="yyyyMMdd/yyyyMMdd"-TimerServer.log"" /> <param name="DatePattern" value="yyyyMMdd/"TimerServer/TimerServer.log"" />--> <!--按照何種方式產生多個日志文件(日期[Date],文件大小[Size],混合[Composite])--> <param name="RollingStyle" value="Date" /> <!--每個文件的大小。只在混合方式與文件大小方式下使用,超出大小的在文件名后自動增加1重新命名--> <param name="maximumFileSize" value="500KB" /> <!--記錄的格式。--> <layout type="log4net.Layout.PatternLayout"> <!-- %d, %date :表示當然的時間 %p, %level :表示日志的級別 %c, %logger :表示日志產生的主題或名稱,通常是所在的類名,便於定位問題 %m, %message :表示日志的具體內容 %n, %newline :換行 %exception :表示異常信息 --> <param name="ConversionPattern" value="%d [%t] %-5p %c - %m %logger %n" /> </layout> </appender> <!-- 文件形式記錄日志-Other --> <appender name="RollingFileAppender_Other" type="log4net.Appender.RollingFileAppender"> <param name= "File" value= "D:\App_Log\Other\"/> <param name= "AppendToFile" value= "true"/> <param name= "MaxSizeRollBackups" value= "10"/> <param name= "StaticLogFileName" value= "false"/> <param name= "DatePattern" value= "yyyy-MM-dd".log""/> <param name="RollingStyle" value="Date" /> <param name="maximumFileSize" value="500KB" /> <layout type="log4net.Layout.PatternLayout"> <param name="ConversionPattern" value="%d [%t] %-5p %c - %m %logger %n" /> </layout> <filter type="log4net.Filter.LevelRangeFilter"> <!-- 控制輸出日志的級別范圍 --> <param name="LevelMin" value="Info" /> <param name="LevelMax" value="Warn" /> </filter> </appender> <!-- name屬性指定其名稱,type則是log4net.Appender命名空間的一個類的名稱,意思是,指定使用哪種介質 --> <!-- 數據庫日志-Debug(每一個appender節點,代表一個記錄日志的方式) --> <appender name="AdoNetAppender_Debug" type="log4net.Appender.AdoNetAppender"> <!--日志緩存寫入條數 設置為0時只要有一條就立刻寫到數據庫 生產環境可改為10-100寫入一次--> <bufferSize value="0" /> <!-- 日志數據庫連接類型(此處寫錯會導致無法寫入數據庫) --> <connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" /> <!-- 日志數據庫連接字符串 --> <connectionString value="Server=127.0.0.1;DataBase=Test; User ID=sa;Password=sa"/> <!-- 日志數據庫執行SQL語句 --> <commandText value="INSERT INTO ApplicationLog_Debug(LogDate, Level, Logger, Message, Exception)VALUES(@logdate, @loglevel, @logger, @message, @exception)"/> <!-- 參數-日志時間 --> <parameter> <parameterName value="@logdate" /> <dbType value="DateTime" /> <layout type="log4net.Layout.RawTimeStampLayout"/> </parameter> <!-- 參數-日志級別 --> <parameter> <parameterName value="@loglevel" /> <dbType value="String" /> <size value="200" /> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="%p" /> </layout> </parameter> <!-- 參數-日志名稱 --> <parameter> <parameterName value="@logger" /> <dbType value="String" /> <size value="500" /> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="%c" /> </layout> </parameter> <!-- 參數-日志內容(size是最大長度,超出則直接去到該長度的內容) --> <parameter> <parameterName value="@message" /> <dbType value="String" /> <size value="4000" /> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="%m" /> </layout> </parameter> <!-- 參數-異常內容(Exception會記錄異常的所有信息,如:System.NullReferenceException: 未將對象引用設置到對象的實例。 在 TestLog4Net.Program.Main(String[] args) 位置 d:\TestDemo_Tyh\TestLog4Net\TestLog4Net\Program.cs:行號 41) --> <parameter> <parameterName value="@exception"/> <dbType value="String"/> <size value="4000"/> <layout type="log4net.Layout.ExceptionLayout"/> </parameter> </appender> <!-- 數據庫日志-Info --> <appender name="AdoNetAppender_Info" type="log4net.Appender.AdoNetAppender"> <!-- 表示是記錄10條到緩沖區,滿10條后再寫入SQL server 調試時可以改為1,實際應用建議為100 --> <bufferSize value="0" /> <!-- 數據庫連接類型 --> <connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" /> <!-- 數據庫連接字符串 --> <connectionString value="Server=127.0.0.1;DataBase=Test; User ID=sa;Password=sa"/> <!-- 執行SQL語句 --> <commandText value="INSERT INTO ApplicationLog_Info(LogDate, Level, Logger, Message, Exception)VALUES(@logdate, @loglevel, @logger, @message, @exception)"/> <!-- 參數賦值 --> <parameter> <parameterName value="@logdate" /> <dbType value="DateTime" /> <layout type="log4net.Layout.RawTimeStampLayout"/> </parameter> <parameter> <parameterName value="@loglevel" /> <dbType value="String" /> <size value="200" /> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="%p" /> </layout> </parameter> <parameter> <parameterName value="@logger" /> <dbType value="String" /> <size value="500" /> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="%logger" /> </layout> </parameter> <parameter> <parameterName value="@message" /> <dbType value="String" /> <size value="4000" /> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="%m" /> </layout> </parameter> <parameter> <parameterName value="@exception"/> <dbType value="String"/> <size value="4000"/> <layout type="log4net.Layout.ExceptionLayout"/> </parameter> </appender> </log4net> </configuration>
3.編寫C#代碼
using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; using log4net; using log4net.Config; namespace TestLog4Net { public class Program { public static void Main(string[] args) { //初始化log4net對象 InitLog4Net(); //創建默認類型的日志對象(傳遞對象類型typeof(Program)可以自動記錄類名稱) var logger = LogManager.GetLogger(typeof(Program)); //創建指定類型的日志對象 var loggerDbDebug = LogManager.GetLogger("logger.db.debug"); var loggerDbInfo = LogManager.GetLogger("logger.db.info");//創建指定類型的文本日志對象 var loggerFileDebug = LogManager.GetLogger("logger.file.debug"); var loggerFileOther = LogManager.GetLogger("logger.file.other"); //寫入默認類型日志 logger.Debug("測試日志");//配置了過濾器不記錄此條信息 logger.Info("測試日志"); logger.Error("測試日志"); //寫入指定類型日志(可以先驗證是否為當前日志級別) if (loggerDbDebug.IsDebugEnabled) loggerDbDebug.Debug("db.debug", new Exception("db.debug.Exception")); if (loggerDbInfo.IsInfoEnabled) loggerDbInfo.Info("db.info", new Exception("db.info.Exception")); //寫入指定類型的文本日志 loggerFileDebug.Debug("file.debug", new Exception("file.debug.Exception")); loggerFileOther.Info("file.info", new Exception("file.info.Exception")); loggerFileOther.Warn("file.warn", new Exception("file.warn.Exception")); loggerFileOther.Error("file.error", new Exception("file.error.Exception"));//配置了過濾器不記錄此條信息 loggerFileOther.Fatal("file.fatal", new Exception("file.fatal.Exception"));//配置了過濾器不記錄此條信息 Console.WriteLine("complete"); Console.ReadKey(); } public static void InitLog4Net() { //配置文件 var logCfg = new FileInfo(AppDomain.CurrentDomain.BaseDirectory + "/Config/log4net.config"); //加載配置 XmlConfigurator.ConfigureAndWatch(logCfg); } } }
4.數據庫表創建(直接用PowerDesigner生成)
if exists (select 1 from sysindexes where id = object_id('ApplicationLog_Debug') and name = 'Index_ApplicationLog_Debug_LogDate' and indid > 0 and indid < 255) drop index ApplicationLog_Debug.Index_ApplicationLog_Debug_LogDate go if exists (select 1 from sysobjects where id = object_id('ApplicationLog_Debug') and type = 'U') drop table ApplicationLog_Debug go /*==============================================================*/ /* Table: ApplicationLog_Debug */ /*==============================================================*/ create table ApplicationLog_Debug ( Id bigint identity, LogDate datetime not null, Level varchar(50) not null, Logger varchar(50) null, Message ntext null, Exception text null, constraint PK_APPLICATIONLOG_DEBUG primary key nonclustered (Id) ) go /*==============================================================*/ /* Index: Index_ApplicationLog_Debug_LogDate */ /*==============================================================*/ create clustered index Index_ApplicationLog_Debug_LogDate on ApplicationLog_Debug ( LogDate DESC ) go
5.運行查看日志記錄