一、log4net簡介:
- Log4net的優點:
幾乎所有的大型應用都會有自己的用於跟蹤調試的API。因爲一旦程序被部署以後,就不太可能再利用專門的調試工具了。然而一個管理員可能需要有一套強大的日誌系統來診斷和修復配置上的問題。
經驗表明,日誌記錄往往是軟件開發週期中的重要組成部分。它具有以下幾個優點:它可以提供應用程序運行時的精確環境,可供開發人員儘快找到應用程序中的Bug;一旦在程序中加入了Log 輸出代碼,程序運行過程中就能生成並輸出日誌信息而無需人工干預。另外,日誌信息可以輸出到不同的地方(控制檯,文件等)以備以後研究之用。
Log4net就是爲這樣一個目的設計的,用於.NET開發環境的日誌記錄包。
- Log4net的安裝:
用戶可以從http://logging.apache.org/log4net/下載log4net的源代碼。解壓軟件包後,在解壓的src目錄下將log4net.sln載入Visual Studio .NET,編譯後可以得到log4net.dll。用戶要在自己的程序里加入日誌功能,只需將log4net.dll引入工程即可。
- Log4net的結構
log4net 有四種主要的組件,分別是Logger(記錄器), Repository(庫), Appender(附着器)以及 Layout(佈局).
二、log4net使用:
1.創建項目 -> 引入log4net.dll -> 添加文件夾命名爲Config -> 添加配置文件命名爲log4net.config
2.編輯log4net.config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<!--註冊log4net(目前註釋掉也可以正常使用)-->
<!--<configSections>
<section name="log4net" type="log4net.Config.IgnoreSectionHandler"/>
</configSections>-->
<log4net>
<!-- 日誌默認值節點 -->
<root>
<!-- 默認日誌對象級別 -->
<!--(高) OFF > FATAL > ERROR > WARN > INFO > DEBUG > ALL (低) -->
<level value="all" />
<!-- 默認日誌記錄方式 ref爲<appender>節點的name屬性-->
<appender-ref ref="MyColoredConsoleAppender"/>
<!--<appender-ref ref="MyRollingFileAppender"/>-->
</root>
<!--
注意!!!
<root>節點和<logger>節點,如果同時出現,
會先執行root的內容,再執行logger的內容,
有可能會出現重複插入記錄的情況,
解決方案:默認節點不設置默認記錄方式
-->
<!-- 指定類別日誌設置節點 name爲LogManager.GetLogger("logger.db.debug")中的name參數 -->
<logger name="logger.db.debug">
<!-- 該日誌對象的級別(可多個級別設置在一起,公用同一個記錄方式)-->
<level value="DEBUG"/>
<!-- 該日誌對象的記錄方式(可多個記錄方式設置在一起,同時記錄到多種媒介上) -->
<appender-ref ref="AdoNetAppender_Debug"/>
</logger>
<logger name="logger.db.info">
<level value="INFO"/>
<appender-ref ref="AdoNetAppender_Info"/>
</logger>
<!-- 文本日誌 -->
<logger name="logger.file.debug">
<level value="DEBUG"/>
<appender-ref ref="RollingFileAppender_Debug"/>
</logger>
<logger name="logger.file.other">
<level value="INFO"/>
<level value="WARN"/>
<appender-ref ref="RollingFileAppender_Other"/>
</logger>
<!--
AdoNetAppender:利用ADO.NET記錄到數據庫的日誌。
ConsoleAppender:將日誌輸出到控制檯。
RollingFileAppender:將日誌以回滾文件(重複操作原始文件)的形式寫到文件中。
-->
<!-- 控制檯顯示日誌 -->
<appender name="MyColoredConsoleAppender" type="log4net.Appender.ColoredConsoleAppender">
<!-- 設置不同級別控制檯顯示的不同顏色 -->
<mapping>
<level value="INFO" />
<foreColor value="Green" />
</mapping>
<mapping>
<level value="ERROR" />
<foreColor value="Red, HighIntensity" />
</mapping>
<!-- 記錄的格式。 -->
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date{HH:mm:ss,fff} [%-5level] %m %n" />
</layout>
<!--
過濾器type有如下幾種類型
log4net.Filter.DenyAllFilter 丟棄所有日誌事件。
log4net.Filter.LevelMatchFilter 準確匹配事件等級。
log4net.Filter.LevelRangeFilter 匹配一個範圍的等級。
log4net.Filter.LoggerMatchFilter 匹配一個日誌器名字的開始。
log4net.Filter.PropertyFilter 匹配指定屬性名稱的子字符串。
log4net.Filter.StringMatchFilter 匹配事件消息的子字符串。
-->
<filter type="log4net.Filter.LevelRangeFilter">
<!-- 控制輸出日誌的級別範圍 -->
<param name="LevelMin" value="Info" />
<param name="LevelMax" value="Error" />
</filter>
</appender>
<!-- 文件形式記錄日誌-Debug -->
<appender name="RollingFileAppender_Debug" type="log4net.Appender.RollingFileAppender">
<!--日誌文件路徑,按文件大小方式輸出時在這裏指定文件名,並且前面的日誌按天在文件名後自動添加當天日期形成文件-->
<param name= "File" value= "D:\App_Log\Debug\"/>
<!--是否是向文件中追加日誌-->
<param name= "AppendToFile" value= "true"/>
<!--記錄日誌寫入文件時,不鎖定文本文件-->
<!--<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />-->
<!--Unicode編碼-->
<!--<Encoding value="UTF-8" />-->
<!--最多產生的日誌文件數,value="-1"爲不限文件數-->
<!--<param name="MaxSizeRollBackups" value="10" />-->
<!--log保留天數-->
<param name= "MaxSizeRollBackups" value= "10"/>
<!--日誌文件名是否是固定不變的(是否只寫到一個文件中)-->
<param name= "StaticLogFileName" value= "false"/>
<!--按日期產生文件夾,文件名[在日期方式與混合方式下使用]日誌文件名格式爲:2008-08-31.log -->
<param name= "DatePattern" value= "yyyy-MM-dd".log""/>
<!--<param name="DatePattern" value="yyyy-MM-dd/"-ReflectionLayout.log="""" />
<param name="DatePattern" value="yyyyMMdd/yyyyMMdd"-TimerServer.log"" />
<param name="DatePattern" value="yyyyMMdd/"TimerServer/TimerServer.log"" />-->
<!--按照何種方式產生多個日誌文件(日期[Date],文件大小[Size],混合[Composite])-->
<param name="RollingStyle" value="Date" />
<!--每個文件的大小。只在混合方式與文件大小方式下使用,超出大小的在文件名後自動增加1重新命名-->
<param name="maximumFileSize" value="500KB" />
<!--記錄的格式。-->
<layout type="log4net.Layout.PatternLayout">
<!--
%d, %date :表示當然的時間
%p, %level :表示日誌的級別
%c, %logger :表示日誌產生的主題或名稱,通常是所在的類名,便於定位問題
%m, %message :表示日誌的具體內容
%n, %newline :換行
%exception :表示異常信息
-->
<param name="ConversionPattern" value="%d [%t] %-5p %c - %m %logger %n" />
</layout>
</appender>
<!-- 文件形式記錄日誌-Other -->
<appender name="RollingFileAppender_Other" type="log4net.Appender.RollingFileAppender">
<param name= "File" value= "D:\App_Log\Other\"/>
<param name= "AppendToFile" value= "true"/>
<param name= "MaxSizeRollBackups" value= "10"/>
<param name= "StaticLogFileName" value= "false"/>
<param name= "DatePattern" value= "yyyy-MM-dd".log""/>
<param name="RollingStyle" value="Date" />
<param name="maximumFileSize" value="500KB" />
<layout type="log4net.Layout.PatternLayout">
<param name="ConversionPattern" value="%d [%t] %-5p %c - %m %logger %n" />
</layout>
<filter type="log4net.Filter.LevelRangeFilter">
<!-- 控制輸出日誌的級別範圍 -->
<param name="LevelMin" value="Info" />
<param name="LevelMax" value="Warn" />
</filter>
</appender>
<!-- name屬性指定其名稱,type則是log4net.Appender命名空間的一個類的名稱,意思是,指定使用哪種介質 -->
<!-- 數據庫日誌-Debug(每一個appender節點,代表一個記錄日誌的方式) -->
<appender name="AdoNetAppender_Debug" type="log4net.Appender.AdoNetAppender">
<!--日誌緩存寫入條數 設置爲0時只要有一條就立刻寫到數據庫 生產環境可改爲10-100寫入一次-->
<bufferSize value="0" />
<!-- 日誌數據庫連接類型(此處寫錯會導致無法寫入數據庫) -->
<connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<!-- 日誌數據庫連接字符串 -->
<connectionString value="Server=127.0.0.1;DataBase=Test; User ID=sa;Password=sa"/>
<!-- 日誌數據庫執行SQL語句 -->
<commandText value="INSERT INTO ApplicationLog_Debug(LogDate, Level, Logger, Message, Exception)VALUES(@logdate, @loglevel, @logger, @message, @exception)"/>
<!-- 參數-日誌時間 -->
<parameter>
<parameterName value="@logdate" />
<dbType value="DateTime" />
<layout type="log4net.Layout.RawTimeStampLayout"/>
</parameter>
<!-- 參數-日誌級別 -->
<parameter>
<parameterName value="@loglevel" />
<dbType value="String" />
<size value="200" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%p" />
</layout>
</parameter>
<!-- 參數-日誌名稱 -->
<parameter>
<parameterName value="@logger" />
<dbType value="String" />
<size value="500" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%c" />
</layout>
</parameter>
<!-- 參數-日誌內容(size是最大長度,超出則直接去到該長度的內容) -->
<parameter>
<parameterName value="@message" />
<dbType value="String" />
<size value="4000" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%m" />
</layout>
</parameter>
<!-- 參數-異常內容(Exception會記錄異常的所有信息,如:System.NullReferenceException: 未將對象引用設置到對象的實例。
在 TestLog4Net.Program.Main(String[] args) 位置 d:\TestDemo_Tyh\TestLog4Net\TestLog4Net\Program.cs:行號 41) -->
<parameter>
<parameterName value="@exception"/>
<dbType value="String"/>
<size value="4000"/>
<layout type="log4net.Layout.ExceptionLayout"/>
</parameter>
</appender>
<!-- 數據庫日誌-Info -->
<appender name="AdoNetAppender_Info" type="log4net.Appender.AdoNetAppender">
<!-- 表示是記錄10條到緩衝區,滿10條後再寫入SQL server 調試時可以改爲1,實際應用建議爲100 -->
<bufferSize value="0" />
<!-- 數據庫連接類型 -->
<connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<!-- 數據庫連接字符串 -->
<connectionString value="Server=127.0.0.1;DataBase=Test; User ID=sa;Password=sa"/>
<!-- 執行SQL語句 -->
<commandText value="INSERT INTO ApplicationLog_Info(LogDate, Level, Logger, Message, Exception)VALUES(@logdate, @loglevel, @logger, @message, @exception)"/>
<!-- 參數賦值 -->
<parameter>
<parameterName value="@logdate" />
<dbType value="DateTime" />
<layout type="log4net.Layout.RawTimeStampLayout"/>
</parameter>
<parameter>
<parameterName value="@loglevel" />
<dbType value="String" />
<size value="200" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%p" />
</layout>
</parameter>
<parameter>
<parameterName value="@logger" />
<dbType value="String" />
<size value="500" />
<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="%m" />
</layout>
</parameter>
<parameter>
<parameterName value="@exception"/>
<dbType value="String"/>
<size value="4000"/>
<layout type="log4net.Layout.ExceptionLayout"/>
</parameter>
</appender>
</log4net>
</configuration>
3.編寫C#代碼
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using log4net;
using log4net.Config;
namespace TestLog4Net
{
public class Program
{
public static void Main(string[] args)
{
//初始化log4net對象
InitLog4Net();
//創建默認類型的日誌對象(傳遞對象類型typeof(Program)可以自動記錄類名稱)
var logger = LogManager.GetLogger(typeof(Program));
//創建指定類型的日誌對象
var loggerDbDebug = LogManager.GetLogger("logger.db.debug");
var loggerDbInfo = LogManager.GetLogger("logger.db.info");//創建指定類型的文本日誌對象
var loggerFileDebug = LogManager.GetLogger("logger.file.debug");
var loggerFileOther = LogManager.GetLogger("logger.file.other");
//寫入默認類型日誌
logger.Debug("測試日誌");//配置了過濾器不記錄此條信息
logger.Info("測試日誌");
logger.Error("測試日誌");
//寫入指定類型日誌(可以先驗證是否爲當前日誌級別)
if (loggerDbDebug.IsDebugEnabled)
loggerDbDebug.Debug("db.debug", new Exception("db.debug.Exception"));
if (loggerDbInfo.IsInfoEnabled)
loggerDbInfo.Info("db.info", new Exception("db.info.Exception"));
//寫入指定類型的文本日誌
loggerFileDebug.Debug("file.debug", new Exception("file.debug.Exception"));
loggerFileOther.Info("file.info", new Exception("file.info.Exception"));
loggerFileOther.Warn("file.warn", new Exception("file.warn.Exception"));
loggerFileOther.Error("file.error", new Exception("file.error.Exception"));//配置了過濾器不記錄此條信息
loggerFileOther.Fatal("file.fatal", new Exception("file.fatal.Exception"));//配置了過濾器不記錄此條信息
Console.WriteLine("complete");
Console.ReadKey();
}
public static void InitLog4Net()
{
//配置文件
var logCfg = new FileInfo(AppDomain.CurrentDomain.BaseDirectory + "/Config/log4net.config");
//加載配置
XmlConfigurator.ConfigureAndWatch(logCfg);
}
}
}
4.數據庫表創建(直接用PowerDesigner生成)
if exists (select 1
from sysindexes
where id = object_id('ApplicationLog_Debug')
and name = 'Index_ApplicationLog_Debug_LogDate'
and indid > 0
and indid < 255)
drop index ApplicationLog_Debug.Index_ApplicationLog_Debug_LogDate
go
if exists (select 1
from sysobjects
where id = object_id('ApplicationLog_Debug')
and type = 'U')
drop table ApplicationLog_Debug
go
/*==============================================================*/
/* Table: ApplicationLog_Debug */
/*==============================================================*/
create table ApplicationLog_Debug (
Id bigint identity,
LogDate datetime not null,
Level varchar(50) not null,
Logger varchar(50) null,
Message ntext null,
Exception text null,
constraint PK_APPLICATIONLOG_DEBUG primary key nonclustered (Id)
)
go
/*==============================================================*/
/* Index: Index_ApplicationLog_Debug_LogDate */
/*==============================================================*/
create clustered index Index_ApplicationLog_Debug_LogDate on ApplicationLog_Debug (
LogDate DESC
)
go
5.運行查看日誌記錄