.Net Core(.NET6)中接入Log4net和NLog進行日誌記錄
一、接入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/"log.log"" /> <!--日誌最大個數,都是最新的--> <!--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的獨立出來。
增加配置信息
完整配置文件


<?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/"log.log"" /> <!--日誌最大個數,都是最新的--> <!--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/"error.log"" /> <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;
增加配置信息
完整配置文件


<?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/"log.log"" /> <!--日誌最大個數,都是最新的--> <!--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/"error.log"" /> <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日誌配置://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="//www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="//www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="//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="//www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="//www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="//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="//www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="//www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="//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.可以很方便的自定義日誌文件名,這個對於核心模塊單獨打日誌太方便了。