一. Log4Net簡介 Log4net是從Java中的Log4j遷移過來的一個.Net版的開源日誌框架,它的功能很強大,可以將日誌分為不同的等級,以不同的格式輸出到不同的存儲介質中,比如:資料庫、txt文件、記憶體緩衝區、郵件、控制台、ANSI終端、遠程接收端等等,我們這裡主要介紹最常用的兩種:tx ...
一. Log4Net簡介
Log4net是從Java中的Log4j遷移過來的一個.Net版的開源日誌框架,它的功能很強大,可以將日誌分為不同的等級,以不同的格式輸出到不同的存儲介質中,比如:資料庫、txt文件、記憶體緩衝區、郵件、控制台、ANSI終端、遠程接收端等等,我們這裡主要介紹最常用的兩種:txt文件和資料庫。
(PS:其它的存儲介質詳見 http://logging.apache.org/log4net/release/config-examples.html)
Log4net將日誌分為五個級別,分別是: FATAL(致命錯誤) > ERROR(一般錯誤) > WARN(警告) > INFO(一般信息) > DEBUG(調試信息),每個級別都對應著一組重載方法進行調用。
官網地址:http://logging.apache.org/log4net/index.html
Nuget地址:https://www.nuget.org/packages/log4net/
Nuget安裝:Install-Package log4net
最新版本:2.0.8 (2018-08-09)
本節主要圍繞兩個主要的存儲介質:【txt文件】和【SQLServer資料庫】展開,涵蓋的知識點有:
①. 基本的使用步驟。
②. 初始化關聯配置文件的幾種形式。
③. 代碼調用詳解。
④. 配置文件詳解。
⑤. 簡單的封裝和在MVC框架中的調用。
二. 基本使用步驟
我們先以控制台程式為例,簡單介紹Log4net存儲日誌到txt文本文檔中,後面在做代碼的詳解。
1. 新建01-SimpleDemo控制台程式,通過指令 【Install-Package log4net】安裝相應程式集。
2. 在預設配置文件中App.config(B/S程式則為web.config)中進行配置,主要分兩塊:
A. 在<configuration></configuration>節點下新增節點下新增(要在其最頂部):
<configSections>
<section name = "log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net" />
</configSections>
B. 在<configuration></configuration>根節點下,配置log4net的核心配置代碼, 主要節點如下:
<log4net> <appender> </appender> <root></root> </log4net>
詳細代碼如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 <?xml version="1.0" encoding="utf-8" ?> 2 <configuration> 3 <!-- 1. 添加log4net的節點聲明配置代碼--> 4 <configSections> 5 <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net" /> 6 </configSections> 7 <!--2. log4net的核心配置代碼--> 8 <log4net> 9 <!--把日誌信息輸出到以日期命名的文件里--> 10 <appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender"> 11 <!--文件夾的位置--> 12 <file value="D:\MyLog1\" /> 13 <appendToFile value="true" /> 14 <!--動態生成文件名--> 15 <param name="StaticLogFileName" value="false" /> 16 <!--以日期命名--> 17 <param name="DatePattern" value="yyyyMMdd".log"" /> 18 <rollingStyle value="Date" /> 19 <!--日誌在日誌文件中的佈局方式--> 20 <layout type="log4net.Layout.PatternLayout"> 21 <conversionPattern value="%newline %n記錄時間:%date %n線程ID:[%thread] %n日誌級別: %-5level %n出錯類:%logger property: [%property{NDC}] - %n錯誤描述:%message%newline %n"/> 22 </layout> 23 <!--使用最小鎖定模型(minimal locking model),以允許多個進程可以寫入同一個文件 --> 24 <lockingModel type="log4net.Appender.FileAppender+MinimalLock" /> 25 </appender> 26 <root> 27 <level value="ALL"></level> 28 <appender-ref ref="RollingFileAppender"></appender-ref> 29 </root> 30 </log4net> 31 <startup> 32 <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6" /> 33 </startup> 34 </configuration>View Code
3. 代碼調用
1 log4net.Config.XmlConfigurator.Configure(); 2 ILog log = LogManager.GetLogger("test"); 3 log.Debug("調試信息");
4. 運行結果
截止此處,日誌保存成功。
三. 初始化配置文件
前面提到在預設配置文件中App.config(B/S程式則為web.config)中進行配置,可以通過代碼 log4net.Config.XmlConfigurator.Configure(); 來初始化配置,或者還可以通過 [assembly: log4net.Config.XmlConfigurator()] 反射的形式進行初始化配置,二者可以達到同樣的效果,代表了兩種初始化配置文件的形式。
PS: [assembly: log4net.Config.XmlConfigurator()] 可以加在 當前使用文件的 namespace上作用於當前文件,或者加在Properties/AssemblyInfo.cs中,則該項目全局都無須再初始化了。
在實際項目中,預設的配置文件里可能包含很多框架的信息,這個時候把 log4net的配置代碼再放入進去,就會顯得有點雜亂,或者有些“奇葩”的人把預設配置文件改名了,這個時候使用上述預設的兩種方式就不好用了,那麼這種情況怎麼處理呢? 這裡重點介紹 通過 log4net.Config.XmlConfigurator.Configure(); 來關聯配置文件。
情況一: 使用預設配置文件的情況
1. 代碼配置:log4net.Config.XmlConfigurator.Configure();
2. 反射配置:[assembly: log4net.Config.XmlConfigurator()]
情況二:修改預設配置文件的名稱為:App1.config (這裡只是舉例,很少有修改預設配置文件名稱的)
1. 代碼配置: 首先將App1.config文件的屬性中的“生成操作”改為“ 嵌入的資源”,然後通過以下代碼進行配置。
1 Assembly assembly = Assembly.GetExecutingAssembly(); 2 var xml = assembly.GetManifestResourceStream("_01_SimpleDemo.App1.config"); 3 log4net.Config.XmlConfigurator.Configure(xml);
註:代碼中的 _01_SimpleDemo 為命名空間名。
2. 反射配置:[assembly: log4net.Config.XmlConfigurator(ConfigFile = "log4net.xml")]
註:用這種方式屬性中的:複製到輸出目錄需要改為:始終複製,生成操作不需要配置,使用預設:無 即可
情況三:新建單獨xml文件,進行log4net的配置 (推薦採用這種方式,和原配置文件區分開,單獨配置方便,處理方式和情況二是一致的)
1. 代碼配置:首先將log4net.xml文件的屬性中的“生成操作”改為“ 嵌入的資源”,然後通過以下代碼進行配置。
1 Assembly assembly = Assembly.GetExecutingAssembly(); 2 var xml = assembly.GetManifestResourceStream("_01_SimpleDemo.log4net.xml"); 3 log4net.Config.XmlConfigurator.Configure(xml);
註:代碼中的 _01_SimpleDemo 為命名空間名。
情況四:無論是修改預設配置文件的名稱為 或者 新建單獨的xml作為配置文件 → 可以通過絕對路徑的方式進行處理 【不推薦這種方式】
1. 直接寫絕對路徑 (註意這種方式【不需要】配置文件屬性為 “嵌入的資源”)
1 log4net.Config.XmlConfigurator.Configure(new FileInfo(@"D:\06-我的開發之路\DotNet體系\05-DotNet框架篇\03-Log4net詳解\Code\01-SimpleDemo\log4net.xml"));
2 通過代碼獲取絕對路徑 (註意這種方式【不需要】配置文件屬性的“生成操作”改為 “嵌入的資源”,但需要改為“始終複製”,確保輸出到bin文件下)
1 string assemblyFilePath = Assembly.GetExecutingAssembly().Location; 2 string assemblyDirPath = Path.GetDirectoryName(assemblyFilePath); 3 string configFilePath = assemblyDirPath + " //log4net.xml"; 4 log4net.Config.XmlConfigurator.Configure(new FileInfo(configFilePath));
PS:B/S程式下通過 log4net.Config.XmlConfigurator.Configure(new FileInfo(Server.MapPath("~") + @"/log4net.xml")); 來配置。
四. 代碼調用詳解
Log4net允許多個ILog對象同時存在,通過代碼:ILog log = LogManager.GetLogger("xxx"); 來創建。
A: 日誌級別由高到低分別為:FATAL(致命錯誤) > ERROR(一般錯誤) > WARN(警告) > INFO(一般信息) > DEBUG(調試信息),另外還有 OFF和 ALL 。
幾點說明:OFF表示所有信息都不寫入,ALL表示所有信息都寫入,我們也可以通過:<root><level value = "WARN" ></ level ></root>這樣配置,表示WARN級別以及高於WARN以上的級別才會被寫入日誌。
B: 寫入日誌的方法有:Debug、Error、Fatal、Info、Warn五個方法,每個方法都有兩個重載,如下圖:
分享在使用配置文件為log4net.xml的情況下的調用代碼:
1 Assembly assembly = Assembly.GetExecutingAssembly(); 2 var xml = assembly.GetManifestResourceStream("_01_SimpleDemo.log4net.xml"); 3 log4net.Config.XmlConfigurator.Configure(xml); 4 ILog log = LogManager.GetLogger("test"); 5 log.Debug("調試信息"); 6 log.Info("一般信息"); 7 log.Warn("警告"); 8 try 9 { 10 int.Parse("ddd"); 11 } 12 catch (Exception ex) 13 { 14 log.Error("一般錯誤", ex); 15 } 16 log.Fatal("致命錯誤");
五. 配置文件詳解
Log4net的配置文件主要分為兩大部分:分別是 【自定義配置節點】和 【核心代碼配置】,自定義配置節點代碼固定,如下圖,核心代碼配置主要位於:<log4net></log4net>節點中,裡面包括<appender></appender>節點配置日日誌輸出途徑 和 <root></root>節點,用於設置記錄日誌的級別和啟用哪些輸出途徑。
幾點說明:
1. 自定義配置節點 <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net" /> 代碼固定,直接複製即可。
2. <root></root> 節點主要用來: 配置日誌的的輸出級別和載入日誌的輸出途徑。
A: level中的value值表示該值及其以上的日誌級別才會輸出,日誌級別包括:OFF > FATAL(致命錯誤) > ERROR(一般錯誤) > WARN(警告) > INFO(一般信息) > DEBUG(調試信息) > ALL ,比如:
<level value="INFO"></level> 表示只有INFO及其以上的日誌級別才會被保存。
PS:OFF表示所有信息都不寫入,ALL表示所有信息都寫入。
B: <appender-ref></appender-ref>標簽用於載入日誌的輸出途徑代碼,通過ref和appender標簽的中name屬性相關聯,比如:
<appender-ref ref="RollingFileAppender"></appender-ref> 表示開啟txt文檔保存日誌的方式。
3. <appender></appender>節點,用來配置日誌的輸出途徑的,本節主要介紹了輸出到 【txt文本文檔】中 和 【資料庫】。
A:分享一下資料庫的表結構,詳細配置見下麵的代碼分享,需要註意欄位類型相匹配,並且要顯式指定其長度。
B:關於txt文本文檔的命名,可以存放到一個文件夾里,也可以按照時間來區分文件夾,並且命名可以 動態+指定命名的方式。
C:關於日誌文件大小的說明和文件個數的說明,主要需要三個節點配合使用(實際開發中,如果一個txt特別大,打開的時候會非常的慢,卡頓,所以該步驟有必要配置一下)。
PS:首先要配置 RollingStyle 節點為Size模式或者Composite模式,然後配置 maximumFileSize 節點設置每個文件的大小,最後配置 MaxSizeRollBackups 節點,設置日誌文件的個數。超出大小後在所有文件名後自動增加正整數重新命名,數字最大的最早寫入。
用下麵的代碼簡單測試一下:
1 <param name="RollingStyle" value="Composite" /> 2 <param name="maximumFileSize" value="10KB" /> 3 <param name="MaxSizeRollBackups" value="5" />
詳細代碼如下:
1 <?xml version="1.0" encoding="utf-8" ?> 2 <configuration> 3 <!-- 一. 添加log4net的自定義配置節點--> 4 <configSections> 5 <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net" /> 6 </configSections> 7 <!--二. log4net的核心配置代碼--> 8 <log4net> 9 <!--(一) 配置日誌的輸出途徑--> 10 <!--1. 輸出途徑(一) 將日誌以回滾文件的形式寫到文件中--> 11 <appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender"> 12 <!--1.1 文件夾的位置(也可以寫相對路徑)--> 13 <param name="File" value="D:\MyLog1\" /> 14 <!--相對路徑 C/S程式生成在Debug目錄下--> 15 <!--<param name="File" value="/Logs/" />--> 16 <!--1.2 是否追加到文件--> 17 <param name="AppendToFile" value="true" /> 18 <!--1.3 使用最小鎖定模型(minimal locking model),以允許多個進程可以寫入同一個文件 --> 19 <lockingModel type="log4net.Appender.FileAppender+MinimalLock" /> 20 <!--1.4 配置Unicode編碼--> 21 <Encoding value="UTF-8" /> 22 <!--1.5 是否只寫到一個文件里--> 23 <param name="StaticLogFileName" value="false" /> 24 <!--1.6 配置按照何種方式產生多個日誌文件 (Date:日期、Size:文件大小、Composite:日期和文件大小的混合方式)--> 25 <param name="RollingStyle" value="Composite" /> 26 <!--1.7 介紹多種日誌的的命名和存放在磁碟的形式--> 27 <!--1.7.1 在根目錄下直接以日期命名txt文件 註意"的位置,去空格 --> 28 <param name="DatePattern" value="yyyy-MM-dd".log"" /> 29 <!--1.7.2 在根目錄下按日期產生文件夾,文件名固定 test.log --> 30 <!--<param name="DatePattern" value="yyyy-MM-dd/"test.log"" />--> 31 <!--1.7.3 在根目錄下按日期產生文件夾,這是按日期產生文件夾,併在文件名前也加上日期 --> 32 <!--<param name="DatePattern" value="yyyyMMdd/yyyyMMdd"-test.log"" />--> 33 <!--1.7.4 在根目錄下按日期產生文件夾,這再形成下一級固定的文件夾 --> 34 <!--<param name="DatePattern" value="yyyyMMdd/"OrderInfor/test.log"" />--> 35 <!--1.8 配置每個日誌的大小。【只在1.6 RollingStyle 選擇混合方式與文件大小方式下才起作用!!!】可用的單位:KB|MB|GB。不要使用小數,否則會一直寫入當前日誌, 36 超出大小後在所有文件名後自動增加正整數重新命名,數字最大的最早寫入。--> 37 <param name="maximumFileSize" value="10MB" /> 38 <!--1.9 最多產生的日誌文件個數,超過則保留最新的n個 將value的值設置-1,則不限文件個數 【只在1.6 RollingStyle 選擇混合方式與文件大小方式下才起作用!!!】 39 與1.8中maximumFileSize文件大小是配合使用的--> 40 <param name="MaxSizeRollBackups" value="5" /> 41 <!--1.10 配置文件文件的佈局格式,使用PatternLayout,自定義佈局--> 42 <layout type="log4net.Layout.PatternLayout"> 43 <conversionPattern value="記錄時間:%date %n線程ID:[%thread] %n日誌級別:%-5level %n出錯類:%logger property: [%property{NDC}] - %n錯誤描述:%message%newline %n%newline"/> 44 </layout> 45 </appender> 46 47 <!--2. 輸出途徑(二) 記錄日誌到資料庫--> 48 <appender name="AdoNetAppender" type="log4net.Appender.AdoNetAppender"> 49 <!--2.1 設置緩衝區大小,只有日誌記錄超設定值才會一塊寫入到資料庫--> 50 <param name="BufferSize" value="1" /> 51 <!--2.2 引用--> 52 <connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" /> 53 <!--2.3 資料庫連接字元串--> 54 <connectionString value="data source=localhost;initial catalog=LogDB;integrated security=false;persist security info=True;User ID=sa;Password=123456" /> 55 <!--2.4 SQL語句插入到指定表--> 56 <commandText value="INSERT INTO LogInfor ([threadId],[log_level],[log_name],[log_msg],[log_exception],[log_time]) VALUES (@threadId, @log_level, @log_name, @log_msg, @log_exception,@log_time)" /> 57 <!--2.5 資料庫欄位匹配--> 58 <!-- 線程號--> 59 <parameter> 60 <parameterName value="@threadId" /> 61 <dbType value="String" /> 62 <size value="100" /> 63 <layout type="log4net.Layout.PatternLayout"> 64 <conversionPattern value="%thread" /> 65 </layout> 66 </parameter> 67 <!--日誌級別--> 68 <parameter> 69 <parameterName value="@log_level" /> 70 <dbType value="String" /> 71 <size value="100" /> 72 <layout type="log4net.Layout.PatternLayout"> 73 <conversionPattern value="%level" /> 74 </layout> 75 </parameter> 76 <!--日誌記錄類名稱--> 77 <parameter> 78 <parameterName value="@log_name" /> 79 <dbType value="String" /> 80 <size value="100" /> 81 <layout type="log4net.Layout.PatternLayout"> 82 <conversionPattern value="%logger" /> 83 </layout> 84 </parameter> 85 <!--日誌信息--> 86 <parameter> 87 <parameterName value="@log_msg" /> 88 <dbType value="String" /> 89 <size value="5000" /> 90 <layout type="log4net.Layout.PatternLayout"> 91 <conversionPattern value="%message" /> 92 </layout> 93 </parameter> 94 <!--異常信息 指的是如Infor 方法的第二個參數的值--> 95 <parameter> 96 <parameterName value="@log_exception" /> 97 <dbType value="String" /> 98 <size value="2000" /> 99 <layout type="log4net.Layout.ExceptionLayout" /> 100 </parameter> 101 <!-- 日誌記錄時間--> 102 <parameter> 103 <parameterName value="@log_time" /> 104 <dbType value="DateTime" /> 105 <layout type="log4net.Layout.RawTimeStampLayout" /> 106 </parameter> 107 </appender> 108 <!--(二). 配置日誌的的輸出級別和載入日誌的輸出途徑--> 109 <root> 110 <!--1. level中的value值表示該值及其以上的日誌級別才會輸出--> 111 <!--OFF > FATAL(致命錯誤) > ERROR(一般錯誤) > WARN(警告) > INFO(一般信息) > DEBUG(調試信息) > ALL --> 112 <!--OFF表示所有信息都不寫入,ALL表示所有信息都寫入--> 113 <level value="ALL"></level> 114 <!--2. append-ref標簽表示要載入前面的日誌輸出途徑代碼 通過ref和appender標簽的中name屬性相關聯--> 115 <appender-ref ref="RollingFileAppender"></appender-ref> 116 <appender-ref ref="AdoNetAppender"></appender-ref> 117 </root> 118 </log4net> 119 120 </configuration>
六. 簡單的封裝及完整代碼分享
這裡模擬在系統框架中對Log4net進行簡單的封裝,然後在MVC框架中調用,並分享全部代碼。
步驟一:新建Ypf.Utils類庫,作為工具類庫,引入log4net程式集,並將前面用到的log4net.xml 複製進來,改屬性為嵌入資源,然後新建LogUtils類(不要起名為LogHelp),對Log4net的方法進行簡單的封裝,主要包括:初始化代碼、ILog實例創建、五類日誌級別的封裝。
log4net.xml文件代碼如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 <?xml version="1.0" encoding="utf-8" ?> 2 <configuration> 3 <!-- 一. 添加log4net的自定義配置節點--> 4 <configSections> 5 <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net" /> 6 </configSections> 7 <!--二. log4net的核心配置代碼--> 8 <log4net> 9