.Net Core(.NET6)中接入Log4net和NLog進行日誌記錄

包子wxl發表於2022-03-16

一、接入Log4net

1.按日期和大小混合分割日誌

nuget包安裝

log4net
Microsoft.Extensions.Logging.Log4Net.AspNetCore

配置檔案

 

 

 配置檔案內容為

<?xml version="1.0" encoding="utf-8"?>
<log4net>
    <!-- Define some output appenders -->
    <appender name="rollingAppender" type="log4net.Appender.RollingFileAppender">
    <!--    value="logs/log.log"-->
        <file value="logs/" />
        <!--追加日誌內容-->
        <appendToFile value="true" />

        <!--防止多執行緒時不能寫Log,官方說執行緒非安全-->
        <lockingModel type="log4net.Appender.FileAppender+MinimalLock" />

        <!--可以為:Once|Size|Date|Composite-->
        <!--Composite為Size和Date的組合-->
        <rollingStyle value="Composite" />

        <!--當備份檔案時,為檔名加的字尾-->
        <datePattern value="yyyyMMdd/&quot;log.log&quot;" />

        <!--日誌最大個數,都是最新的-->
        <!--rollingStyle節點為Size時,只能有value個日誌-->
        <!--rollingStyle節點為Composite時,每天有value個日誌-->
        <maxSizeRollBackups value="20" />

        <!--可用的單位:KB|MB|GB-->
        <maximumFileSize value="3MB" />

        <!--置為true,當前最新日誌檔名永遠為file節中的名字-->
        <staticLogFileName value="false" />

        <!--輸出級別在INFO和ERROR之間的日誌-->
        <filter type="log4net.Filter.LevelRangeFilter">
            <param name="LevelMin" value="ALL" />
            <param name="LevelMax" value="FATAL" />
        </filter>
        <layout type="log4net.Layout.PatternLayout">
            <conversionPattern value="%date [%thread] %-5level %logger - %message%newline"/>
        </layout>
    </appender>
    <root>

        <!--控制級別,由低到高: ALL|DEBUG|INFO|WARN|ERROR|FATAL|OFF-->
        <!--OFF:0-->
        <!--FATAL:FATAL-->
        <!--ERROR: ERROR,FATAL-->
        <!--WARN: WARN,ERROR,FATAL-->
        <!--INFO: INFO,WARN,ERROR,FATAL-->
        <!--DEBUG: INFO,WARN,ERROR,FATAL-->
        <!--ALL: DEBUG,INFO,WARN,ERROR,FATAL--> 
        <priority value="ALL"/>
        
        <level value="INFO"/>
        <!--使用上面配置的那個規則,ref指定上面的規則名稱-->
        <appender-ref ref="rollingAppender" />
    </root>
</log4net>

程式引入,Program.cs檔案增加

 

 

 

builder.Logging.AddLog4Net("Configs/log4net.Config");

//Nuget引入:
//1.Log4Net
//2.Microsoft.Extensions.Logging.Log4Net.AspNetCore
builder.Services.AddControllersWithViews();

程式使用

 public class HomeController : Controller
    {
        private readonly ILogger<HomeController> _logger;

        public HomeController(ILogger<HomeController> logger)
        {
            _logger = logger;
        }

        public IActionResult Index()
        {
            _logger.LogInformation($"{this.GetType()},info,介面訪問");
            _logger.LogError($"{this.GetType()},error,介面訪問錯誤");
            return View();
        }
}

效果:

 

 

 

 

 

2.日誌分級獨立資料夾顯示

上面全部等級的日誌資訊都顯示在同一個資料夾,如果想找error資訊,如果日誌量大並不好查詢,所以把error的獨立出來。

增加配置資訊

 

 完整配置檔案

.Net Core(.NET6)中接入Log4net和NLog進行日誌記錄
<?xml version="1.0" encoding="utf-8"?>
<log4net>
    <!-- Define some output appenders -->
    <appender name="rollingAppender" type="log4net.Appender.RollingFileAppender">
    <!--    value="logs/log.log"-->
        <file value="logs/" />
        <!--追加日誌內容-->
        <appendToFile value="true" />

        <!--防止多執行緒時不能寫Log,官方說執行緒非安全-->
        <lockingModel type="log4net.Appender.FileAppender+MinimalLock" />

        <!--可以為:Once|Size|Date|Composite-->
        <!--Composite為Size和Date的組合-->
        <rollingStyle value="Composite" />

        <!--當備份檔案時,為檔名加的字尾-->
        <datePattern value="yyyyMMdd/&quot;log.log&quot;" />

        <!--日誌最大個數,都是最新的-->
        <!--rollingStyle節點為Size時,只能有value個日誌-->
        <!--rollingStyle節點為Composite時,每天有value個日誌-->
        <maxSizeRollBackups value="20" />

        <!--可用的單位:KB|MB|GB-->
        <maximumFileSize value="3MB" />

        <!--置為true,當前最新日誌檔名永遠為file節中的名字-->
        <staticLogFileName value="false" />

        <!--輸出級別在INFO和ERROR之間的日誌-->
        <filter type="log4net.Filter.LevelRangeFilter">
            <param name="LevelMin" value="ALL" />
            <param name="LevelMax" value="FATAL" />
        </filter>
        <layout type="log4net.Layout.PatternLayout">
            <conversionPattern value="%date [%thread] %-5level %logger - %message%newline"/>
        </layout>
    </appender>
    <!-- error日誌 -->
    <appender name="errorAppender" type="log4net.Appender.RollingFileAppender">
        <file value="logs/" />
        <appendToFile value="true" />
        <lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
        <rollingStyle value="Composite" />
        <datePattern value="yyyyMMdd/&quot;error.log&quot;" />
        <maxSizeRollBackups value="20" />
        <maximumFileSize value="3MB" />
        <staticLogFileName value="false" />
        <filter type="log4net.Filter.LevelRangeFilter">
            <param name="LevelMin" value="ERROR" />
            <param name="LevelMax" value="ERROR" />
        </filter>
        <layout type="log4net.Layout.PatternLayout">
            <conversionPattern value="%date [%thread] %-5level %logger - %message%newline"/>
        </layout>
    </appender>
    <root>

        <!--控制級別,由低到高: ALL|DEBUG|INFO|WARN|ERROR|FATAL|OFF-->
        <!--OFF:0-->
        <!--FATAL:FATAL-->
        <!--ERROR: ERROR,FATAL-->
        <!--WARN: WARN,ERROR,FATAL-->
        <!--INFO: INFO,WARN,ERROR,FATAL-->
        <!--DEBUG: INFO,WARN,ERROR,FATAL-->
        <!--ALL: DEBUG,INFO,WARN,ERROR,FATAL--> 
        <priority value="ALL"/>
        
        <level value="INFO"/>
        <!--使用上面配置的那個規則,ref指定上面的規則名稱-->
        <appender-ref ref="rollingAppender" />
        <appender-ref ref="errorAppender" />
    </root>
</log4net>
View Code

執行,日誌列印效果

 

 

 

 

3.log4net日誌寫入資料庫

這裡以log4net寫入Mysql為示例

引入Nuget包

MySql.Data

資料庫日誌表指令碼

CREATE TABLE `logs` (
  `log_id` bigint NOT NULL AUTO_INCREMENT,
  `app_name` varchar(100) NOT NULL,
  `log_date` datetime NOT NULL,
  `thread` varchar(100) NOT NULL,
  `level` varchar(50) NOT NULL,
  `logger` varchar(255) NOT NULL,
  `message` varchar(1000) NOT NULL,
  `exception` varchar(2000) NOT NULL,
  PRIMARY KEY (`log_id`)
) ENGINE=InnoDB AUTO_INCREMENT=36 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

 

增加配置資訊

 

 

 

 

完整配置檔案

 

.Net Core(.NET6)中接入Log4net和NLog進行日誌記錄
<?xml version="1.0" encoding="utf-8"?>
<log4net>
    <!-- Define some output appenders -->
    <appender name="rollingAppender" type="log4net.Appender.RollingFileAppender">
    <!--    value="logs/log.log"-->
        <file value="logs/" />
        <!--追加日誌內容-->
        <appendToFile value="true" />

        <!--防止多執行緒時不能寫Log,官方說執行緒非安全-->
        <lockingModel type="log4net.Appender.FileAppender+MinimalLock" />

        <!--可以為:Once|Size|Date|Composite-->
        <!--Composite為Size和Date的組合-->
        <rollingStyle value="Composite" />

        <!--當備份檔案時,為檔名加的字尾-->
        <datePattern value="yyyyMMdd/&quot;log.log&quot;" />

        <!--日誌最大個數,都是最新的-->
        <!--rollingStyle節點為Size時,只能有value個日誌-->
        <!--rollingStyle節點為Composite時,每天有value個日誌-->
        <maxSizeRollBackups value="20" />

        <!--可用的單位:KB|MB|GB-->
        <maximumFileSize value="3MB" />

        <!--置為true,當前最新日誌檔名永遠為file節中的名字-->
        <staticLogFileName value="false" />

        <!--輸出級別在INFO和ERROR之間的日誌-->
        <filter type="log4net.Filter.LevelRangeFilter">
            <param name="LevelMin" value="ALL" />
            <param name="LevelMax" value="FATAL" />
        </filter>
        <layout type="log4net.Layout.PatternLayout">
            <conversionPattern value="%date [%thread] %-5level %logger - %message%newline"/>
        </layout>
    </appender>
    <!-- error日誌 -->
    <appender name="errorAppender" type="log4net.Appender.RollingFileAppender">
        <file value="logs/" />
        <appendToFile value="true" />
        <lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
        <rollingStyle value="Composite" />
        <datePattern value="yyyyMMdd/&quot;error.log&quot;" />
        <maxSizeRollBackups value="20" />
        <maximumFileSize value="3MB" />
        <staticLogFileName value="false" />
        <filter type="log4net.Filter.LevelRangeFilter">
            <param name="LevelMin" value="ERROR" />
            <param name="LevelMax" value="ERROR" />
        </filter>
        <layout type="log4net.Layout.PatternLayout">
            <conversionPattern value="%date [%thread] %-5level %logger - %message%newline"/>
        </layout>
    </appender>
    <!--SqlServer形式-->
    <!--log4net日誌配置:http://logging.apache.org/log4net/release/config-examples.html -->
    <appender name="mysqlAppender" type="log4net.Appender.AdoNetAppender">
        <!--日誌快取寫入條數 設定為0時只要有一條就立刻寫到資料庫-->
        <bufferSize value="0" />
        <connectionType value="MySql.Data.MySqlClient.MySqlConnection, MySql.Data" />
        <connectionString value="server=127.0.0.1;database=test_db;user=root;pwd=123456;SslMode=none" />
        <commandText value="INSERT INTO logs(app_name,log_date, thread, `level`, logger, message, `exception`)VALUES(@app_name,@log_date, @thread,@log_level, @logger, @message, @exception);" />
        <parameter>
            <parameterName value="@app_name" />
            <dbType value="String" />
            <size value="100" />
            <layout type="log4net.Layout.PatternLayout" >
                <conversionPattern value="api" />
            </layout>
        </parameter>
        <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="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="1000" />
            <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>
    <root>

        <!--控制級別,由低到高: ALL|DEBUG|INFO|WARN|ERROR|FATAL|OFF-->
        <!--OFF:0-->
        <!--FATAL:FATAL-->
        <!--ERROR: ERROR,FATAL-->
        <!--WARN: WARN,ERROR,FATAL-->
        <!--INFO: INFO,WARN,ERROR,FATAL-->
        <!--DEBUG: INFO,WARN,ERROR,FATAL-->
        <!--ALL: DEBUG,INFO,WARN,ERROR,FATAL--> 
        <priority value="ALL"/>
        
        <level value="INFO"/>
        <!--使用上面配置的那個規則,ref指定上面的規則名稱-->
        <appender-ref ref="rollingAppender" />
        <appender-ref ref="errorAppender" />
        <appender-ref ref="mysqlAppender" />
    </root>
</log4net>
View Code

 

效果

 

 

 

如果是SqlServer

引入Nuget包

System.Data.SqlClient

 connectionType寫上SqlServer的連線型別

<connectionType value="System.Data.SqlClient.SqlConnection,System.Data.SqlClient, Version=4.6.1.3, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />

連線字串處改成SqlServer的連線字串即可。

二、接入NLog

1.寫文字日誌

引入Nuget包

NLog.Web.AspNetCore

配置檔案內容

<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://www.nlog-project.org/schemas/NLog.xsd NLog.xsd"
      autoReload="true"
      throwExceptions="false"
      internalLogLevel="Off" internalLogFile="NLog\all_log.log">

  <targets>
      <!--檔案日誌,archive相關引數:檔案拆分,每100M拆分一個新檔案-->
      <target xsi:type="File" 
            name="all_log"
            fileName="NLog\${shortdate}\${uppercase:${level}}.log"
            layout="${longdate}|${logger}|${uppercase:${level}}|${message} ${exception}"
            archiveFileName="NLog\${shortdate}\${uppercase:${level}}${shortdate}.{####}.log"
            archiveNumbering="Rolling"
            archiveAboveSize="10485760"
            concurrentwrites="true"
            maxArchiveFiles="100"
              />

  </targets>
    

  <rules> 
    <!-- add your logging rules here -->
      <!--路由順序會對日誌列印產生影響。路由匹配邏輯為順序匹配。-->
      <logger name="*" minlevel="Trace" writeTo="all_log" />
  </rules>
</nlog>

 

 程式引入NLog

 

 

程式使用:

 

結果:

 

 

 

2.過濾日誌

有一些元件自帶了日誌的,像上面的Microsoft.*開頭就是.Net Core自帶的,我們想遮蔽掉一些dll的日誌怎麼弄呢

修改配置規則

 

 

 

 效果:

 

 

 

 

3.自定義日誌檔名

很多時候我們想把比較重要的功能的日誌單獨寫到一個日誌檔案方便排查,NLog提供了單獨打日誌檔案的功能

修改配置檔案,用一個屬性接收,屬性由程式端傳來:${event-properties:filename}

<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://www.nlog-project.org/schemas/NLog.xsd NLog.xsd"
      autoReload="true"
      throwExceptions="false"
      internalLogLevel="Off" internalLogFile="NLog\all_log.log">

  <targets>
      <!--檔案日誌,archive相關引數:檔案拆分,每100M拆分一個新檔案-->
      <target xsi:type="File" 
            name="all_log"
            fileName="NLog\${shortdate}\${event-properties:filename}${shortdate}.log"
            layout="${longdate}|${logger}|${uppercase:${level}}|${message} ${exception}"
            archiveFileName="NLog\${shortdate}\${event-properties:filename}${shortdate}.{####}.log"
            archiveNumbering="Rolling"
            archiveAboveSize="10485760"
            concurrentwrites="true"
            maxArchiveFiles="100"
              />
  </targets>

  <rules> 
    <!-- add your logging rules here -->
      <!--路由順序會對日誌列印產生影響。路由匹配邏輯為順序匹配。-->
      
      <!--Skip Microsoft logs and so log only own logs-->
      <!--以Microsoft打頭的日誌將進入此路由,由於此路由沒有writeTo屬性,所有會被忽略-->
      <!--且此路由設定了final,所以當此路由被匹配到時。不會再匹配此路由下面的路由。未匹配到此路由時才會繼續匹配下一個路由-->
      <logger name="Microsoft.*" minlevel="Trace"  final="true" />
      <logger name="*" minlevel="Trace" writeTo="all_log" />
  </rules>
</nlog>

封裝一個LogHelper.cs

 public class LogHelper
    {
        private static Logger logger= LogManager.GetCurrentClassLogger();
        public static void Info(string message,string fileName="INFO")
        {
            //把檔名通過屬性傳輸
            logger.WithProperty("filename", fileName).Info(message);
        }
        public static void Debug(string message, string fileName = "DEBUG")
        {
            logger.WithProperty("filename", fileName).Debug(message);
        }
        public static void Error(string message, string fileName = "Error")
        {
            logger.WithProperty("filename", fileName).Error(message);
        }
        public static void Warn(string message, string fileName = "Warn")
        {
            logger.WithProperty("filename", fileName).Warn(message);
        }

    }

程式呼叫:

效果:

 

 

 

 

4.NLog寫入資料庫

這裡以Mysql為例

 引入Nuget包

MySql.Data

sql表指令碼還是上面Log4net一樣。

配置

<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://www.nlog-project.org/schemas/NLog.xsd NLog.xsd"
      autoReload="true"
      throwExceptions="false"
      internalLogLevel="Off" internalLogFile="NLog\all_log.log">

  <targets>
      <!--檔案日誌,archive相關引數:檔案拆分,每100M拆分一個新檔案-->
      <target xsi:type="File" 
            name="all_log"
            fileName="NLog\${shortdate}\${event-properties:filename}${shortdate}.log"
            layout="${longdate}|${logger}|${uppercase:${level}}|${message} ${exception}"
            archiveFileName="NLog\${shortdate}\${event-properties:filename}${shortdate}.{####}.log"
            archiveNumbering="Rolling"
            archiveAboveSize="10485760"
            concurrentwrites="true"
            maxArchiveFiles="100"
              />
      
      <target name="mysql_log" xsi:type="Database"
   dbProvider="MySql.Data.MySqlClient.MySqlConnection, MySql.Data"
   connectionString="server=127.0.0.1;database=test_db;user=root;pwd=123456;SslMode=none"
   commandText="INSERT INTO logs(app_name,log_date, thread, `level`, logger, message, `exception`)VALUES(@app_name,@log_date, @thread,@log_level, @logger, @message, @exception);">
           <parameter name="@app_name" layout="AspNetCoreNlog" />
          <parameter name="@log_date" layout="${date}" />
          <parameter name="@thread" layout="${threadid}" />
          <parameter name="@log_level" layout="${level}" />
          <parameter name="@logger" layout="${logger}" />
          <parameter name="@message" layout="${message}" />
          <parameter name="@exception" layout="${exception:tostring}" />
      </target>
     
  </targets>
    

  <rules> 
    <!-- add your logging rules here -->
      <!--路由順序會對日誌列印產生影響。路由匹配邏輯為順序匹配。-->
      
      <!--Skip Microsoft logs and so log only own logs-->
      <!--以Microsoft打頭的日誌將進入此路由,由於此路由沒有writeTo屬性,所有會被忽略-->
      <!--且此路由設定了final,所以當此路由被匹配到時。不會再匹配此路由下面的路由。未匹配到此路由時才會繼續匹配下一個路由-->
      <logger name="Microsoft.*" minlevel="Trace"  final="true" />
      <logger name="*" minlevel="Trace" writeTo="all_log" />
      <logger name="*" minlevel="Trace" writeTo="mysql_log" />
  </rules>
</nlog>

 

效果:

 

 

 

如果寫SqlServer

引入Nuget包

System.Data.SqlClient
dbProvider="System.Data.SqlClient.SqlConnection, System.Data.SqlClient"
connectionString改為SqlServer的連線字串即可

5.Log4Net對比NLog

Log4Net對比NLog來說效能相差無幾

但是個人推薦用NLog,原因有

1.配置簡單

2.可以很方便的自定義日誌檔名,這個對於核心模組單獨打日誌太方便了。

相關文章