1. 程式人生 > >關於Log4Net的使用及配置方式

關於Log4Net的使用及配置方式

目錄

  • 0.簡介
  • 1.安裝程式包
  • 2.配置檔案示例
  • 3.日記的級別:Level
  • 4.日誌的輸出源:Appenders
  • 5.日誌格式:Layout
  • 6.日誌檔案變換方式(回滾方式):RollingStyle
  • 7.日誌的過濾器:Filter
  • 8.將日誌記錄在資料庫中
  • 9.記入日誌的原則
  • 10.參考
  • 11.完整的案例原始碼
志銘-2020年1月17日 23:18:37

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="&quot;Logs_&quot;yyyyMMdd&quot;.txt&quot;" /><!--日誌檔名為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" />

    見 6.日誌檔案變換方式(回滾方式):RollingStyle

  • <layout type="log4net.Layout.PatternLayout,log4net">

    見5.2格式示例1

  • 日誌寫入檔案時,不鎖定文字檔案,防止多執行緒時不能寫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="&quot;Logs_&quot;yyyyMMdd&quot;.txt&quot;" />
      <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="&quot;Errors_&quot;yyyyMMdd&quot;.txt&quot;" />
      <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後,把異常寫入日誌.

.在呼叫第三方控制元件的開始和結束處.

.在連線資料庫的開始結束處.

.除非必要,不要在迴圈體中加入日誌,否則一旦出問題可能導致日誌暴增.

.在自己認為很重要的邏輯處寫入日誌.




10.參考

  • 部落格園:使用Log4net記錄日誌

  • 知乎:別在程式碼裡亂打日誌了,這才是正確的打日誌姿勢!

  • CSDN:ASP.NET MVC的最佳日誌記錄庫

  • CSDN:非常完善的Log4net詳細說明

  • CSDN:關於日誌的那些事兒

  • CSDN:我的log4net使用手冊(完善中)




11.完整的案例原始碼

下載地址