首页 > 代码库 > 程序的记事本--log4net

程序的记事本--log4net

 你是否在遇到程序运行问题时经常百度?你是否在遇到运行错误时经常去询问别人?如果有那么是时候改变啦,对于一个Developer来说那是不专业的表现,专业的Developer都会首先查看程序的运行日志,先从日志下手,分析问题发生的原因,然后修复它。这里面最重要的就是日志,那么你也就会很好奇,这些日志是如何记录的呢,偷偷的告诉你通常使用的是日志管理框架。那么是不是也想在开发程序时开发出一个日志管理的模块呢,不用着急下面就来介绍下如何做日志管理。

        就我所知现在日志管理框架有多种如 Enterprise、NLog、CLog、Log4net,其中Log4net功能强大适用于中大型的项目日志管理,NLog虽然功能较少但是它使用简单,而且支持智能感应,另外Enterprise更是强大的没的说,针对于大型系统开发,当然使用也比较困难。但是考虑到它们的使用资源及功能的强大,最后我们的项目确定了使用Log4net,所以接下来将会主要讨论Log4net的主要使用方法。

一、Log4net组成及配置


        从Log4net的API文档中不难看出,其实Log4net的开发过程还是蛮简单的,并没有想象中的那么复杂,而且在使用时只需要添加相应的配置节信息然后调用存储方法即可实现日志的存储,具体的结构如下图

技术分享


  1.1 组成详解

        上图显示了Log4net的主要由五个部分组成,分别为Logger,Appenders, Filters, Layouts 和Object Renders,其中最主要的Appender命名空间中封装了日志的存储方式,也就是说通过配置Appender能够将日志输出到执行的类型中;Layout其实是封装了数据显示的格式,通过配置Layout能够输出指定模板的数据信息,它还可以控制数据的输出类型(输出xml还是文本类型);Object Renders很重要,它能够控制数据的自定义输出,log4net将会按照用户定义的标准输出日志。


  1.2 配置方法

        在使用log4net时首先需要配置日志存储方式,然后在代码中调用LogManager类的静态方法GetLog保存对象的对象的信息。其中配置信息可以写到config文件内,也可以自定义一个xml文档,把具体的配置节信息写到xml文件即可。

二、使用方法


       log4net有多重存储级别,按照日志信息的情况大致分为了5类,它们分别是Error错误日志、Fatal严重错误日志、Info一般信息日志、Debug调试信息日志和Warn警告信息日志,在日志管理时可以按照日志的级别来考虑存放的方式,对于严重日志往往是系统的重大问题,此时可以考虑存到服务器数据库中,其它的一些日志可以考虑存储到文件中,可以提高服务器性能。接下来将会介绍它的几种使用方法。


    2.1 日志输出到DataBase

        把日志输出到数据库中也是很多系统经常使用的日志存储方法,在小数据量的处理过程中将日志保存到数据库中是可行的,但是如果需要处理的日志数据量较大那么这种存储方法就会降低数据库的性能,所以在存储日志时慎重使用这种方式,建议涉及到系统重大问题时采用此种存储方式,这样会提升数据库的性能。具体配置如下:

[html] view plain copy 技术分享技术分享
  1. <appender name="AdoNetAppender_SqlServer" type="log4net.Appender.AdoNetAppender">  
  2.   <bufferSize value="1"></bufferSize>  
  3.   <connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />  
  4.   <connectionString value="Data Source=.;Initial Catalog=Test;Integrated Security=True;Pooling=False" />  
  5.   <commandText value="INSERT INTO Log ([Date],[Thread],[Level],[Logger],[Message]) VALUES (@log_date, @thread, @log_level, @logger, @message)" />  
  6.   <parameter>  
  7.     <parameterName value="@log_date" />  
  8.     <dbType value="DateTime" />  
  9.     <layout type="log4net.Layout.PatternLayout" value="%date{yyyy‘-‘MM‘-‘dd HH‘:‘mm‘:‘ss‘.‘fff}" />  
  10.   </parameter>  
  11.   <parameter>  
  12.     <parameterName value="@thread" />  
  13.     <dbType value="String" />  
  14.     <size value="255" />  
  15.     <layout type="log4net.Layout.PatternLayout" value="%thread" />  
  16.   </parameter>  
  17.   <parameter>  
  18.     <parameterName value="@log_level" />  
  19.     <dbType value="String" />  
  20.     <size value="50" />  
  21.     <layout type="log4net.Layout.PatternLayout" value="%level" />  
  22.   </parameter>  
  23.   <parameter>  
  24.     <parameterName value="@logger" />  
  25.     <dbType value="String" />  
  26.     <size value="255" />  
  27.     <layout type="log4net.Layout.PatternLayout" value="%logger" />  
  28.   </parameter>  
  29.   <parameter>  
  30.     <parameterName value="@message" />  
  31.     <dbType value="String" />  
  32.     <size value="4000" />  
  33.     <layout type="log4net.Layout.PatternLayout" value="%message" />  
  34.   </parameter>  
  35. </appender>  

       另外初学者在写入数据库时可能会有很多问题,最主要的是不能写入数据,这主要是由于connectionType和connectionString的原因,要重新检查修改才可以,尤其是connectionType中sqlconnection的版本问题,如果不能成功写入数据往往就是它造成的。

   2.2 日志输出到File

      另外我们也可以将数据输出到文件中,用户可以自定义文件输出的类型,通过datePattern标签来设置存储文件的类型及文件名,具体如下配置所示:
[html] view plain copy 技术分享技术分享
  1. <log4net>  
  2.   <!--定义输出到文件中-->  
  3.     <appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">  
  4.       <file value="D:\" />  
  5.       <appendToFile value="true" />  
  6.       <rollingStyle value="Date" />  
  7.       <maxSizeRollBackups value="30" />  
  8.       <datePattern value="yyyy-MM-dd‘.log‘" />  
  9.       <staticLogFileName value="false" />  
  10.       <layout type="log4net.Layout.PatternLayout">  
  11.         <conversionPattern value="{%level}%date{MM/dd HH:mm:ss} - %message%newline" />  
  12.       </layout>  
  13.     </appender>  
  14.   <root>  
  15.     <!--文件形式记录日志-->  
  16.     <appender-ref ref="RollingLogFileAppender" />        
  17.   </root>  
  18.   
  19. </log4net>  


       此种方式在指定的目录下创建指定的文件,并将日志信息写入创建的文件中。

   2.3 日志输出到Console

       输出到控制台中已经不陌生,在windows操作系统中经常可以看到错误信息,这种方式能够很直观的告诉用户错误的情况及原因,但是这种方式只是缓存级别的,系统重新启动时错误信息就会被删除,所以在使用此种方法时应配合着上面说到的方法来综合存储日志,增强系统的健壮性。
[html] view plain copy 技术分享技术分享
  1. <log4net>  
  2.   <!--定义输出到控制台命令行中-->  
  3.   <appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender">  
  4.     <layout type="log4net.Layout.PatternLayout">  
  5.       <conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline" />  
  6.     </layout>  
  7.   </appender>  
  8.    <root>  
  9.        <!--控制台控制显示日志-->  
  10.     <appender-ref ref="ConsoleAppender" />      
  11.   </root>  
  12.   
  13. </log4net>  

技术分享


    2.4 日志输出到Event

       上面介绍了几种常用的输出方式,当然log4net还有更多的输出方式,这里再介绍一种输出到WindowsEvent的方法,这种方法将会把错误信息输出到Windows事件中,虽然不经常使用,但也可以作为一种日志的存储方式。
[html] view plain copy 技术分享技术分享
  1. <log4net>  
  2.   <!--定义输出到windows事件中-->  
  3.   <appender name="EventLogAppender" type="log4net.Appender.EventLogAppender">  
  4.     <layout type="log4net.Layout.PatternLayout">  
  5.       <conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline" />  
  6.     </layout>  
  7.   </appender>  
  8.    <!--定义日志的输出媒介,下面定义日志以四种方式输出。也可以下面的按照一种类型或其他类型输出。-->  
  9.   <root>  
  10.     <!--Windows事件日志-->  
  11.     <appender-ref ref="EventLogAppender" />  
  12.         
  13.   </root>  
  14.   
  15. </log4net>  

 通过使用上面的配置文件能够将日志输出到指定的类型中,但是想要输出日志并不只是使用上面的配置,另外需要在代码中调用方法来记录日志,具体如下:
[csharp] view plain copy 技术分享技术分享
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Reflection;  
  5. using System.Text;  
  6. using System.Threading.Tasks;  
  7. using log4net;  
  8. using log4net.Appender;  
  9.   
  10. [assembly: log4net.Config.XmlConfigurator(Watch = true)]  
  11. namespace ConsoleApplication1  
  12. {  
  13.     class Program  
  14.     {  
  15.         static void Main(string[] args)  
  16.         {  
  17.             ILog log = log4net.LogManager.GetLogger(typeof(Program));  
  18.             //记录错误日志  
  19.             log.Error("error"new Exception("发生了一个异常"));  
  20.             //记录严重错误  
  21.             log.Fatal("fatal"new Exception("发生了一个致命错误"));  
  22.             //记录一般信息  
  23.             log.Info("info");  
  24.             //记录调试信息  
  25.             log.Debug("debug");  
  26.             //记录警告信息  
  27.             log.Warn("warn");  
  28.             Console.WriteLine("日志记录完毕。");  
  29.             Console.Read();  
  30.         }  
  31.     }  
  32. }  

      在测试时上面的所有形式的配置输出都可以使用GetLogger方法来存储存储日志信息。

   Note:代码中有这么一句:[assembly: log4net.Config.XmlConfigurator(Watch = true)](在需要使用log4net的类的namespace处),如果没有这句就会在调试时得到如下留言中所说的“程序调试起来时isDebugEnable"的情况。

三、log4net保存NHibernate日志信息

       在使用NHibernate时常常需要分析SQL语句,但是NHibernate默认的是不输出SQL Script的,那么怎样才能查看它生成的SQL呢?不妨使用下log4net吧,log4net可以输出NHibernate的运行情况,可以通过配置来实现输出所有Level的NHibernate的日志信息,具体的配置方法如下,这里将配置文件放到了外置的xml中。
[html] view plain copy 技术分享技术分享
  1. <?xml version="1.0" encoding="utf-8" ?>  
  2. <log4net debug="true">  
  3.   <appender name="rollingFile" type="log4net.Appender.RollingFileAppender,log4net">  
  4.     <param name="File" value="D:\log\log.txt"/>  
  5.     <param name="AppendToFile" value="false"/>  
  6.     <param name="RollingStyle" value="Date"/>  
  7.     <param name="StaticLogFileName" value="true"/>  
  8.     <layout type="log4net.Layout.PatternLayout">  
  9.       <param name="ConversionPattern" value="%d [%t] %-5p %c - %m%n" />  
  10.     </layout>  
  11.   </appender>  
  12.   
  13.   <logger name="NHibernate" additivity="true">  
  14.     <level value="ERROR"/>  
  15.     <appender-ref ref="DebugAppender" />  
  16.   </logger>  
  17.   <logger name="NHibernate.SQL" additivity="true">  
  18.     <level value="DEBUG"/>  
  19.     <appender-ref ref="DebugAppender" />  
  20.   </logger>  
  21.   
  22.   <logger name="NHibernate.AdoNet.AbstractBatcher" additivity="true">  
  23.     <level value="DEBUG"/>  
  24.     <appender-ref ref="DebugAppender" />  
  25.   </logger>  
  26.   
  27.   <root>  
  28.     <!-- levels: DEBUG, INFO, WARN, ERROR, FATAL -->  
  29.     <level value="DEBUG"/>  
  30.     <level value="INFO"/>  
  31.     <level value="WARN"/>  
  32.     <level value="ERROR"/>  
  33.     <level value="FATAL "/>  
  34.     <appender-ref ref="rollingFile"/>  
  35.   </root>  
  36. </log4net>  

    这里将log4net的配置信息放到了一个单独的xml文件中,所以需要在运行时将配置信息添加到log4net的配置类中,它的配置往往在Global文件的Application_Start事件中添加配置,如下代码:

[csharp] view plain copy 技术分享技术分享
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Web;  
  5. using System.Web.Security;  
  6. using System.Web.SessionState;  
  7. using Medici.Etam.Data.NHibernateSessionManagement;  
  8. using NHibernate;  
  9. using NHibernate.Context;  
  10.   
  11. namespace Medici.Etam.WebService  
  12. {  
  13.     public class Global : System.Web.HttpApplication  
  14.     {  
  15.         private static log4net.ILog logger = log4net.LogManager.GetLogger("Logger");  
  16.   
  17.         protected void Application_Start(object sender, EventArgs e)  
  18.         {  
  19.     //if the log4net is a lone file then it should be config  
  20.             log4net.XmlConfigurator.Configure(new FileInfo("D:\\Code\\Etam\\ETAM\\ETAM_Webservice_T16_V1.1\\Data\\log4net.cfg.xml"));          
  21.        }  
  22.   
  23.     }  
  24. }  

   

结语

    log4net的日志存储功能很强大,它对日志信息做了详细的分类,总共划分为5类,在存储日志的时候可以根据情况来选择性的存储,并根据级别选择存储方式。另外类似的这种日志框架还有NLog、CLog等,可以根据具体的日志情况来选择使用日志存储的框架。

程序的记事本--log4net