0.簡介
- Log4Net庫是Apache log4j框架在 .NET平台下的實現,其開源免費。它可以將日志分不同的等級,以不同的格式,輸出到不同的媒介。
- 官網地址:http://logging.apache.org/log4net/index.html
- Log4Net開源地址:https://github.com/apache/logging-log4net/
1.安裝程序包
- NuGet:
Install-Package log4net -Version 2.0.8
- 我發現網上一些關於Log4Net的配置的文章中的配置在我的項目中無法運行,所以以下關於Log4Net的使用是在基於 .net 4.6.1的 ASP .NET MVC項目中,開發工具VS2015。
2.配置文件示例
在項目(此處為Web項目)的配置文件Web.config中添加配置信息
2.1注意事項:
-
"<configSections>"節點必須配置在<configuration>之后的第一個位置,
否則報錯,提示:“只允許一個 <configSections> 元素。它必須是根 <configuration> 元素第一個子元素”
-
可以有多個" <appender name="XXXX"> </appender>",只要在"<root></root>"中添加相應的“<appender-ref ref="XXXX">”
即可以設置多個日志輸出的形式,下面我們是把日志以txt文件的形式保存在App_Data/Log文件夾中的 -
在ASP .NET MVC項目中使用Log4Net,首先要在Global.asax.cs中初始化Log4Net,即添加
log4net.Config.XmlConfigurator.Configure();
2.2示例
<!-- ................為Log4Net添加的配置.....開始................-->
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net" />
</configSections>
<log4net>
<root>
<level value="DEBUG" /><!--定義此記錄器的日志記錄級別。此記錄器僅接受此級別(此處即DEBUG級別)或更高級別的事件-->
<appender-ref ref="RollingFileTracer" />
</root>
<appender name="RollingFileTracer" type="log4net.Appender.RollingFileAppender,log4net">
<param name="File" value="App_Data/Log/" /><!--日志文件的保存位置為:App_Data/Log/Log.txt-->
<param name="AppendToFile" value="false" /><!--日志文件為后續內容附加到已有文件(若是false,則為后續覆蓋向前的內存)-->
<param name="RollingStyle" value="Composite" /><!--根據文件的大小和日期滾動文件-->
<param name="MaxSizeRollBackups" value="10" /><!--備份文件的個數-->
<param name="MaximumFileSize" value="1MB" /><!--如果我們將最大文件大小設置為1MB並將maxSizeRollBackups設置為10 MB,那么根據日期或文件大小,它將只保留最后10MB的文件-->
<param name="DatePattern" value=""Logs_"yyyyMMdd".txt"" /><!--日志文件名為Logs_20200114.txt的類似格式-->
<param name="StaticLogFileName" value="false" /><!--日志文件名,是否固定不變-->
<layout type="log4net.Layout.PatternLayout,log4net"> <!--日志記錄的格式-->
<!--<param name="ConversionPattern" value="%d [%t] %-5p %c - %m%n" />格式為:時間+[線程]+級別+項目.Controller -messsage+exception.innerMessage-->
<param name="ConversionPattern" value="記錄時間:%date 線程ID:[%thread] 日志級別:%-5level 出錯類:%logger property:[%property{NDC}] - 錯誤描述:%message%newline" />
<!--格式類似:記錄時間:2020-01-15 20:34:37,946 線程ID:[6] 日志級別:DEBUG 出錯類:_008Log4Net.Controllers.HomeController property:[(null)] - 錯誤描述:Hi I am log4net Debug Level-->
</layout>
</appender>
</log4net>
<!-- ................為Log4Net添加的配置.....結束................-->
2.3配置細節說明
-
<level value="DEBUG" />
寫入日記的級別:DEBUG以上級別(包含該級別)
-
<param name="File" value="App_Data/Log/" />
日志的保存位置:
App_Data/Log/
, 因為App_Data文件夾下的文件無法被用戶下載,不希望訪問者下載的文件放到這里(如果是控制台項目是生成到 bin\Debug 下) -
<param name="AppendToFile" value="false" />
日志文件為后續內容附加到已有文件(若是false,則為后續覆蓋向前的內存)
-
<param name="RollingStyle" value="Composite" />
-
<layout type="log4net.Layout.PatternLayout,log4net">
-
日志寫入文件時,不鎖定文本文件,防止多線程時不能寫Log,
官方說線程非安全,所以示例中沒有寫此配置,若是需要可以添加:
<param name="lockingModel" type="log4net.Appender.FileAppender+MinimalLock" />
3.日記的級別:Level
-
在Log4Net中日志的level: OFF > FATAL > ERROR > WARN > INFO > DEBUG > ALL
-
一般正式項目中只記錄InFo以上
-
Undone:怎么區分級別(什么時候用什么等級)
4.日志的輸出源:Appenders
Appenders用來定義日志的輸出方式,可以保存為文件,可以保存到數據庫,可以發送郵件,可以寫到遠程接收端。
Appender節點下可以配置Filters和Layout來實現日志的過濾和輸出格式
在配置文件中配置如下:
<appender name="RollingFileTracer" type="log4net.Appender.RollingFileAppender,log4net">
其中的type屬性可以設置日志保存的方式,具體的type參數值可以查閱 :非常完善的Log4net詳細說明
常用的兩種方式:
- type="log4net.Appender.RollingFileAppender" 表示將日志以回滾文件的形式寫到文件中。
- type="log4net.Appender.AdoNetAppender"表示將日志記錄到數據庫中。
5.日志格式:Layout
在配置的Layout節點中可以設置日記記錄的格式
5.1設置格式的參數
%m(message):輸出的日志消息,如ILog.Debug(…)輸出的一條消息
%n(new line):換行
%d(datetime):輸出當前語句運行的時刻
%r(run time):輸出程序從運行到執行到當前語句時消耗的毫秒數
%t(thread id):當前語句所在的線程ID
%p(priority):等同於:%level 日志的當前優先級別,即DEBUG、INFO、WARN…等
%c(class):當前日志對象的名稱
%f(file):輸出語句所在的文件名。
%l(line):輸出語句所在的行號。
%數字:表示該項的最小長度,如果不夠,則用空格填充,如“%-5level”表示level的最小寬度是5個字符,如果實際長度不夠5個字符則以空格填充。(因為日志的幾個等級的單詞長度不一樣,通過設置字符長度,可以示日志更加整齊)
5.2格式示例1
上面的配置文件中的格式:
<!--日志記錄的格式-->
<layout type="log4net.Layout.PatternLayout,log4net">
<param name="ConversionPattern" value="記錄時間:%date 線程ID:[%thread] 日志級別:%-5level 出錯類:%logger property:[%property{NDC}] - 錯誤描述:%message%newline" />
<!--格式類似:-->
</layout>
按照上述布局,每一條日志的格式類似:
記錄時間:2020-01-15 20:34:37,946 線程ID:[6] 日志級別:DEBUG 出錯類:_008Log4Net.Controllers.HomeController property:[(null)] - 錯誤描述:Hi I am log4net Debug Level
5.3格式示例2
<!--日志記錄的格式-->
<layout type="log4net.Layout.PatternLayout,log4net">
<param name="ConversionPattern" value="%d [%t] %-5p %c - %m%n" />
</layout>
按照上述布局,每一條日志的格式類似:
2020-01-15 21:09:17,362 [6] DEBUG _008Log4Net.Controllers.HomeController - Hi I am log4net Debug Level
5.4格式示例3
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%newline %n記錄時間:%date %n線程ID:[%thread] %n日志級別: %-5level %n出錯類:%logger property: [%property{NDC}] - %n錯誤描述:%message%newline %n"/>
</layout>
按照上述布局,每一條日志的格式類似:
記錄時間:2020-01-15 22:51:44,106
線程ID:[7]
日志級別: ERROR
出錯類:_008Log4Net.Controllers.HomeController property: [(null)] -
錯誤描述:Hi I am log4net Error Level
System.NullReferenceException: 未將對象引用設置到對象的實例。
在 _008Log4Net.Controllers.HomeController.Index() 位置 F:\ForGit\ASP.NET MVC\008Log4Net\Controllers\HomeController.cs:行號 29
6.日志文件變換方式(回滾方式):RollingStyle
6.1 三種日志回滾方式
回滾方式即按照何種方式產生多個日志文件
-
<param name="RollingStyle" value="XXXX" />
按照何種方式產生多個日志文件,其中value參數的可選值:
Date
(日期),Size
(文件大小),Composite
(混合)
6.2 按照混合模式回滾
-
<param name="RollingStyle" value="Composite" />
按照混合模式產生多個日志文件(即既考慮時間,也文件考慮大小)
上述示例中的選擇使用混合模式生成日志文件,即一定時間內達到一定大小則生成新的一個日志文件
以下兩個節點設置日志文件的大小和數量
-
<param name="MaxSizeRollBackups" value="10" />
最大變換數量,如果超過這個數量則從第一個文件開始復寫(即最多保持10個日志文件)
-
<param name="MaximumFileSize" value="1MB" />
最大文件大小為1MB,支持KB,MB,GB
注意根據以上兩個參數:我們將最大文件大小設置為1MB並將文件變換數量設置為10,那么根據日期或文件大小,它將只保留最后(1*10)MB大小的日志文件。
具體根據項目一定時間內可能產生的日志大小,可以進行文件大小和文件數量的合理分配。
6.3 按照時間回滾
<rollingStyle value="Date"/>
(注意這種寫法和<param name="RollingStyle" value="Date" />
等價)
示例:實現日志每一天一個文件夾,每一分鍾一個文件
<!-- ................為Log4Net添加的配置.....開始................-->
<!---->
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net" />
</configSections>
<log4net>
<root>
<level value="ALL"/>
<appender-ref ref="RollingLogFileAppender"/>
</root>
<appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender,log4net">
<file value="App_Data/Log/"/>
<appendToFile value="true"/>
<rollingStyle value="Date"/><!--按照時間回滾 -->
<!--<datePattern value="yyyy\\yyyyMM\\yyyyMMdd'.txt'"/>--><!--日志文件夾格式:2020/202001/20200117.txt-->
<datePattern value="yyyyMMdd\\yyyyMMddhhmm'.txt'"/><!--日志文件夾格式:20200117/202001170307.txt-->
<staticLogFileName value="false"/>
<!--待研究:日志到底是保留多少,怎么自動刪除就日志-->
<MaxSizeRollBackups value="3"/> <!--定義文件最大個數,超過按順序刪除-->
<maximumFileSize value="6KB" />
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
<filter type="log4net.Filter.LevelRangeFilter">
<levelMin value="ERROR" />
<levelMax value="FATAL" />
</filter>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%newline %n記錄時間:%date %n線程ID:[%thread] %n日志級別: %-5level %n出錯類:%logger property: [%property{NDC}] - %n錯誤描述:%message%newline %n"/>
</layout>
</appender>
</log4net>
<!-- ................為Log4Net添加的配置.....結束................-->
6.4 按照文件大小回滾
<param name="RollingStyle" value="Size" />
<param name="MaxSizeRollBackups" value="10" />
<param name="MaximumFileSize" value="1MB" />
示例:Undone
7.日志的過濾器:Filter
filter可以過濾不同等級的日志
按照:OFF > FATAL > ERROR > WARN > INFO > DEBUG > ALL的順序可以設置一個范圍
實例:將不同級別的日記記錄在不同的日志文件中
<!-- ................為Log4Net添加的配置.....開始................-->
<!--實現日志分等級記錄在不同的日志文件中-->
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net" />
</configSections>
<log4net>
<root>
<level value="ALL"/>
<!--在root節點中設置為記錄日記的所有等級-->
<appender-ref ref="RollingFile"/>
<appender-ref ref="RollingFileTracer"/>
</root>
<appender name="RollingFile" type="log4net.Appender.RollingFileAppender,log4net">
<param name="File" value="App_Data/Log/" />
<param name="AppendToFile" value="true" />
<param name="RollingStyle" value="Composite" />
<param name="MaxSizeRollBackups" value="10" />
<param name="MaximumFileSize" value="1MB" />
<param name="DatePattern" value=""Logs_"yyyyMMdd".txt"" />
<param name="StaticLogFileName" value="false" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="[%-5p %t] [%date{yyyy-MM-dd HH:mm:ss,fff}] %-5logger - %m%n"/>
</layout>
<filter type="log4net.Filter.LevelRangeFilter">
<!--使用過濾器,過濾出WARN > INFO > DEBUG 等級並記錄Logs_20200117.txt-->
<levelMin value="DEBUG" />
<levelMax value="WARN" />
</filter>
</appender>
<appender name="RollingFileTracer" type="log4net.Appender.RollingFileAppender,log4net">
<param name="File" value="App_Data/Log/" />
<param name="AppendToFile" value="true" />
<param name="RollingStyle" value="Composite" />
<param name="MaxSizeRollBackups" value="10" />
<param name="MaximumFileSize" value="1MB" />
<param name="DatePattern" value=""Errors_"yyyyMMdd".txt"" />
<param name="StaticLogFileName" value="false" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="[%p] %m%n"/>
</layout>
<filter type="log4net.Filter.LevelRangeFilter">
<!--使用過濾器,過濾出FATAL > ERROR等級並記錄在Errors_20200117.txt(在程序中將拋異的日志記錄為ERROR和FATAL等級)-->
<levelMin value="ERROR" />
<levelMax value="FATAL" />
</filter>
</appender>
</log4net>
<!--................為Log4Net添加的配置.....結束................-->
8.將日志記錄在數據庫中
示例:將日記記錄在MS SQL Server數據庫中
在MS SQLServer中新建一個庫,添加一個db_Log表,存放日記信息
建表SQL:
CREATE TABLE [dbo].[Log](
[Id] [int] IDENTITY(1,1) NOT NULL,
[Date] [datetime] NOT NULL,
[Thread] [varchar](255) NOT NULL,
[Level] [varchar](50) NOT NULL,
[Logger] [varchar](255) NOT NULL,
[Message] [varchar](4000) NOT NULL,
[Exception] [varchar](2000) NULL
) ON [PRIMARY]
配置信息:
<!-- ...................為Log4Net添加的配置.....開始...................-->
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net" />
</configSections>
<!-- 數據庫連接字符串 -->
<connectionStrings>
<add name="ConnectionStringLogging" connectionString="server=.;database=db_Tome1;uid=sa;pwd=shanzm"
providerName="System.Data.SqlClient" />
</connectionStrings>
<log4net>
<root>
<level value="ALL"></level>
<appender-ref ref="AdoNetAppender"></appender-ref>
</root>
<appender name="AdoNetAppender" type="log4net.Appender.AdoNetAppender">
<bufferSize value="1" />
<connectionType value="System.Data.SqlClient.SqlConnection,System.Data,
Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<connectionStringName value="ConnectionStringLogging" />
<commandText value="INSERT INTO Log ([Date],[Thread],[Level],[Logger],[Message],[Exception])
VALUES (@log_date, @thread, @log_level, @logger, @message, @exception)" />
<parameter>
<parameterName value="@log_date" />
<dbType value="DateTime" />
<layout type="log4net.Layout.RawTimeStampLayout" />
</parameter>
<parameter>
<parameterName value="@thread" />
<dbType value="String" />
<size value="255" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%thread" />
</layout>
</parameter>
<parameter>
<parameterName value="@log_level" />
<dbType value="String" />
<size value="50" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%level" />
</layout>
</parameter>
<parameter>
<parameterName value="@logger" />
<dbType value="String" />
<size value="255" />
<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="%message" />
</layout>
</parameter>
<parameter>
<parameterName value="@exception" />
<dbType value="String" />
<size value="2000" />
<layout type="log4net.Layout.ExceptionLayout" />
</parameter>
</appender>
</log4net>
<!-- ...................為Log4Net添加的配置.....結束...................-->
按照以上方式配置,存放在數據庫中的日志類似如下:
9.記入日志的原則
最后從網上找了一段寫日志的原則:
.在catch后,把異常寫入日志.
.在調用第三方控件的開始和結束處.
.在連接數據庫的開始結束處.
.除非必要,不要在循環體中加入日志,否則一旦出問題可能導致日志暴增.
.在自己認為很重要的邏輯處寫入日志.