一、log4net简介:
1. Log4net的优点:
几乎所有的大型应用都会有自己的用于跟踪调试的API。因为一旦程序被部署以后,就不太可能再利用专门的调试工具了。然而一个管理员可能需要有一套强大的日志系统来诊断和修复配置上的问题。
经验表明,日志记录往往是软件开发周期中的重要组成部分。它具有以下几个优点:它可以提供应用程序运行时的精确环境,可供开发人员尽快找到应用程序中的Bug;一旦在程序中加入了Log 输出代码,程序运行过程中就能生成并输出日志信息而无需人工干预。另外,日志信息可以输出到不同的地方(控制台,文件等)以备以后研究之用。
Log4net就是为这样一个目的设计的,用于.NET开发环境的日志记录包。
2. Log4net的安装:
用户可以从http://logging.apache.org/log4net/下载log4net的源代码。解压软件包后,在解压的src目录下将log4net.sln载入Visual Studio .NET,编译后可以得到log4net.dll。用户要在自己的程序里加入日志功能,只需将log4net.dll引入工程即可。
3. 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.运行查看日志记录