现在的位置: 首页 > 综合 > 正文

c# 开发log4net使用说明

2013年10月07日 ⁄ 综合 ⁄ 共 9096字 ⁄ 字号 评论关闭

最近做项目需要简单的记录日志,所以决定采用log4net做。

在网上看了些例程,都说不是很难,但是实际操作起来还是因为不熟悉有些小问题。

在这里把配置过程以及容易出问题的地方分享一下。

 

1. 首先下载log4net的dll链接库

下载地址:http://logging.apache.org/log4net/

在vs里添加dll引用的时候,一开始不知道不同的.net框架的区别,所以导致了dll不能使用,报错说是使用了不在目标框架的程序集。

这里要特别注意你使用的dll是什么框架下编译的,目前vs2010创建普通C#项目,都是使用的.net framework 4.0 client profile的框架,最开始我也不清楚这个框架和.net framework 4.0有什么区别,后来查了一下,大致区别就是.net client client profile是.net framework的精简版,面向客户端应用程序开发的,所以如果在.net framework client profile框架下进行开发,就要引用你下载的log4net对应的cp文件夹下的dll文件。

 

2. 添加dll引用,然后引用log4net命名空间。

至于log4net的理论部分,我这里不详细说,网上有很多大牛们写的log4net的理论部分,我只简单的说一些我的理解。

理论部分的相关参考链接:

http://logging.apache.org/log4net/release/manual/configuration.html

http://blog.csdn.net/weixingstudio/article/details/8587760

http://blog.csdn.net/weixingstudio/article/details/8587015

http://blog.csdn.net/weixingstudio/article/details/8586328

http://blog.csdn.net/weixingstudio/article/details/8586305

 

从理论上来说,log4net主要有四个部分:分别是Logger(记录器), Repository(库), Appender(附着器)以及 Layout(布局)

其中,记录器就是用来记录日志的,一个记录器可以对应多个附加器,附加器用来指定将日志输出到指定的位置,每个附加器只能指定一个布局模式,只能指定一个。

这样就是说,log4net可以将日志输出到文件,系统日志,数据库,控制台,以及其他例如邮件系统等很多地方,但是常用的就是输出到文件,系统日志,数据库以及控制台。

在下面的例子中主要给出了输出到文件以及滚动文件的配置,输出到数据库的配置还请参考网络其他资料。

 

在log4net中还有一个比较重要的概念,就是属性继承,所有的记录器都继承父类的基本属性,就是父类记录器的属性,如果父类不能实现某些功能,那么子类也不能实现这样的功能。

所以在配置文件中都一般有一个<root>节点,这个节点就是指定父类记录器的属性。

 

    <root>
      <level value="ALL"/>
      <!--文件形式记录日志-->
      <appender-ref ref="LogFileAppender"/>
      <appender-ref ref="LogRollingFileAppender"/>
      <appender-ref ref="RollingLogFileAppender2"/>
      <appender-ref ref="RollingLogFileAppender3"/>
    </root>

上面的配置中,定义了父类记录器的级别,就是所有都记录,以及父类记录器能够附加的附加器,可以看到这里父类附加了四个附加器,那么所有的其他的新生成的附加器都能附加这四个附加器,但是不能附加其他的附加器。

当初我在做项目的时候,没有注意这个问题,只在上面的配置文件中添加了"LogFileAppender"这一个附加器,但是还配置了滚动文件附加器,但是就是没法使用,后来才发现没有在根日志记录器中进行配置。所以要特别注意。

 

总体来说,log4net通过xml文件进行配置,但是这个配置文件,不一定按照指定的名字,网上有些人说要在你的可执行文件的名字后面加上.config后缀作为配置文件名,有些说可以在App.config中进行配置,通过我的学习了解,你想使用什么文件,什么格式的配置都可以,只要设置程序能找到这个配置文件。

 

这里,我采用了在项目的App.config文件中进行配置,注意,App.config文件并不是本来就有,在项目中需要手动添加一下这个文件。

我的简单的配置文件:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net"/>
  </configSections>
  <log4net>

    <!-- 定义根节点的基本属性 -->
    <root>
      <level value="ALL"/>
      <!--文件形式记录日志-->
      <appender-ref ref="LogFileAppender"/>
      <appender-ref ref="LogRollingFileAppender"/>
      <appender-ref ref="RollingLogFileAppender2"/>
      <appender-ref ref="RollingLogFileAppender3"/>
    </root>

    <!-- 定义一个日志对象-->
    <logger name="AventadorLog">
      <level value="ALL"/>
      <appender-ref ref="LogFileAppender"/>
      <appender-ref ref="LogRollingFileAppender"/>
    </logger>


    <!--定义输出到单个日志记录文件中-->
    <appender name="LogFileAppender" type="log4net.Appender.FileAppender">
      <!--定义文件存放路径-->
      <file value="log_single.txt"/>
      <!--是追加还是覆盖文件,true则为追加;false为覆盖-则每次打开程序都会把原来的日志信息删除-->
      <!--<appendToFile value="false"/>-->
      <appendToFile value="true"/>
      <layout type="log4net.Layout.PatternLayout">
        <!--每条日志末尾的文字说明-->
        <footer value="BIT"/>
        <!--日志内容-->
        <conversionPattern value="记录时间:%date %n线程ID:[%thread] %n日志级别:%-5level %n出错类:%logger property:[%property{NDC}] - %n错误描述:%message%newline%n--------------------------------------------------------------------------%n"/>
      </layout>
    </appender>
    
    
    <!--循环记录文件 按照文件大小进行分别存放log信息-->
    <appender name="LogRollingFileAppender" type="log4net.Appender.RollingFileAppender">
      <!--定义文件存放路径-->
      <file value="log.txt"/>
      <!--是否追加到文件-->
      <appendToFile value="true"/>
      <!--记录日志写入文件时,不锁定文本文件,防止多线程时不能写Log,官方说线程非安全-->
      <lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
      <rollingStyle value="Size"/>
      <!--使用Unicode编码-->
      <Encoding value="UTF-8" />
      <!--最多产生的日志文件数,超过则只保留最新的n个。设定值value="-1"为不限文件数-->
      <maxSizeRollBackups value="10"/>
      <maximumFileSize value="10KB"/>
      <!--是否只写到一个文件中-->
      <staticLogFileName value="true"/>
      <layout type="log4net.Layout.PatternLayout">
        <!--每条日志末尾的文字说明-->
        <footer value="BIT"/>
        <!--日志内容-->
        <conversionPattern value="记录时间:%date %n线程ID:[%thread] %n日志级别:%-5level %n出错类:%logger property:[%property{NDC}] - %n错误描述:%message%newline%n--------------------------------------------------------------------------%n"/>
      </layout>
    </appender>

    <!--循环记录文件,按照时间存放日志记录 每分钟内的日志文件输出到一个文件中,新的一分钟输出到新的文件中-->
    <appender name="RollingLogFileAppender2" type="log4net.Appender.RollingFileAppender">
      <file value="logfile" />
      <appendToFile value="true" />
      <rollingStyle value="Date" />
      <datePattern value="yyyyMMdd-HHmm" />
      <layout type="log4net.Layout.PatternLayout">
        <!--每条日志末尾的文字说明-->
        <footer value="BIT"/>
        <!--日志内容-->
        <conversionPattern value="记录时间:%date %n线程ID:[%thread] %n日志级别:%-5level %n出错类:%logger property:[%property{NDC}] - %n错误描述:%message%newline%n--------------------------------------------------------------------------%n"/>
      </layout>
    </appender>

    <!--循环记录日志文件,按照时间记录,在时间内分文件大小进行记录日志-->
    <appender name="RollingLogFileAppender3" type="log4net.Appender.RollingFileAppender">
      <file value="CompositeLog" />
      <appendToFile value="true" />
      <rollingStyle value="Composite" />
      <datePattern value="yyyyMMdd" />
      <maxSizeRollBackups value="10" />
      <maximumFileSize value="2KB" />
      <layout type="log4net.Layout.PatternLayout">
        <!--每条日志末尾的文字说明-->
        <footer value="BIT"/>
        <!--日志内容-->
        <conversionPattern value="记录时间:%date %n线程ID:[%thread] %n日志级别:%-5level %n出错类:%logger property:[%property{NDC}] - %n错误描述:%message%newline%n--------------------------------------------------------------------------%n"/>
      </layout>
    </appender>
    
  </log4net>
  
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
  </startup>
</configuration>

简单的对上面的配置文件进行说明:

<configSections> 

<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net"/> 
</configSections>

这部分设置,说明了log4net框架配置文件的节点名称为<log4net>,所以不管你的配置文件名称为什么,配置文件放在什么目录里,log4net框架都会自动的寻找这个配置文件,然后将<log4net>节点下面的内容作为配置内容。

 

<!-- 定义根节点的基本属性 -->
    <root>
      <level value="ALL"/>
      <!--文件形式记录日志-->
      <appender-ref ref="LogFileAppender"/>
      <appender-ref ref="LogRollingFileAppender"/>
      <appender-ref ref="RollingLogFileAppender2"/>
      <appender-ref ref="RollingLogFileAppender3"/>
    </root>

定义根节点的基本属性,根节点同时决定了其他的日志记录器能够使用的附加器的数量类别。不同的附加器一般将日志输出到不同的介质。

 

<!-- 定义一个日志对象-->
    <logger name="AventadorLog">
      <level value="ALL"/>
      <appender-ref ref="LogFileAppender"/>
      <appender-ref ref="LogRollingFileAppender"/>
    </logger>

定义一个日志对象,同时给出了这个日志对象的附加器,表示日志可以输出到这两个附加器。

这部分配置可有可无,相当于在代码中提前定义了一个名字为AventadorLog的实例对象,在代码中可以找到这个日志对象,通过

            log4net.ILog Logger = log4net.LogManager.GetLogger("AventadorLog");

但是不做上面这部分配置也可以,LogManager如果遇到不存在日志记录器名字,就会创建一个,然后从根记录器那里继承属性。

 

然后就是记录器了:

 <!--定义输出到单个日志记录文件中-->
    <appender name="LogFileAppender" type="log4net.Appender.FileAppender">
      <!--定义文件存放路径-->
      <file value="log_single.txt"/>
      <!--是追加还是覆盖文件,true则为追加;false为覆盖-则每次打开程序都会把原来的日志信息删除-->
      <!--<appendToFile value="false"/>-->
      <appendToFile value="true"/>
      <layout type="log4net.Layout.PatternLayout">
        <!--每条日志末尾的文字说明-->
        <footer value="BIT"/>
        <!--日志内容-->
        <conversionPattern value="记录时间:%date %n线程ID:[%thread] %n日志级别:%-5level %n出错类:%logger property:[%property{NDC}] - %n错误描述:%message%newline%n--------------------------------------------------------------------------%n"/>
      </layout>
    </appender>

上面的例子给出了记录到一个文件的记录器配置,一个记录器对应一个Layout

指定记录器对应的文件的名字,就会自动的创建文件。

 

下面的例子给出一个循环记录器(滚动记录器),自动的根据日志文件的大小创建新的日志文件:

<!--循环记录文件 按照文件大小进行分别存放log信息-->
    <appender name="LogRollingFileAppender" type="log4net.Appender.RollingFileAppender">
      <!--定义文件存放路径-->
      <file value="log.txt"/>
      <!--是否追加到文件-->
      <appendToFile value="true"/>
      <!--记录日志写入文件时,不锁定文本文件,防止多线程时不能写Log,官方说线程非安全-->
      <lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
      <rollingStyle value="Size"/>
      <!--使用Unicode编码-->
      <Encoding value="UTF-8" />
      <!--最多产生的日志文件数,超过则只保留最新的n个。设定值value="-1"为不限文件数-->
      <maxSizeRollBackups value="10"/>
      <maximumFileSize value="10KB"/>
      <!--是否只写到一个文件中-->
      <staticLogFileName value="true"/>
      <layout type="log4net.Layout.PatternLayout">
        <!--每条日志末尾的文字说明-->
        <footer value="BIT"/>
        <!--日志内容-->
        <conversionPattern value="记录时间:%date %n线程ID:[%thread] %n日志级别:%-5level %n出错类:%logger property:[%property{NDC}] - %n错误描述:%message%newline%n--------------------------------------------------------------------------%n"/>
      </layout>
    </appender>

然后还有根据时间创建日志文件的记录器配置:

<!--循环记录文件,按照时间存放日志记录 每分钟内的日志文件输出到一个文件中,新的一分钟输出到新的文件中-->
    <appender name="RollingLogFileAppender2" type="log4net.Appender.RollingFileAppender">
      <file value="logfile" />
      <appendToFile value="true" />
      <rollingStyle value="Date" />
      <datePattern value="yyyyMMdd-HHmm" />
      <layout type="log4net.Layout.PatternLayout">
        <!--每条日志末尾的文字说明-->
        <footer value="BIT"/>
        <!--日志内容-->
        <conversionPattern value="记录时间:%date %n线程ID:[%thread] %n日志级别:%-5level %n出错类:%logger property:[%property{NDC}] - %n错误描述:%message%newline%n--------------------------------------------------------------------------%n"/>
      </layout>
    </appender>

时间和滚动也可以共同使用,同一个时间段内,如果日志大小超出设置,可以创建新的文件,这里不重复给出例子,请看上面的完整配置文件。

 

 

3. 引用配置文件

有了配置文件以后,就需要在程序中指定使用哪个配置文件,这里网上也是众说纷纭,我觉得最好的解决办法还是在AssemblyInfo.cs文件中设置比较好,这样比较协调。

在AssemblyInfo.cs文件最后面添加下面的代码:

[assembly: log4net.Config.XmlConfigurator(ConfigFileExtension="config",Watch = true)]

 

ConfigFileExtension="config", 的意思是指定配置文件的扩展名为config,这样Log4net框架会自动的找到配置文件。

也可以使用ConfigFile="ABC.exe.config",指定具体的配置文件以及配置问价扩展名,还可以指定配置文件的路径,但是这两个配置不能同时使用。

 

4. 日志记录

 

设置好以后,就可以在程序中记录日志了。

一般都采用反射原理记录当前类的异常,当然不采用反射获取当前类的类名也可以。

 private void button1_Click(object sender, EventArgs e)
        {
            log4net.ILog Logger = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
            int count = 100;
            for (int i = 0; i < count; i++)
            {
                Logger.Info("鼠标点击按钮发生");
                Logger.Debug("debug");
                Logger.Warn("warn");
                Logger.Fatal("fatal");
            }
            MessageBox.Show("done");
        }

上面方法中采用了反射机制获取当前类的名称,并记录在日志中哪个类的调用出错了。

其他的都很简单了。

抱歉!评论已关闭.