Log4net的配置学习与总结

 

1 Log4net的结构

       Log4net 有四种主要的组件,分别是logger(记录器)、Repository(库)、Appender(附着器)以及Layout(布局)。

1.1   Logger

Logger是应用程序需要交互的主要组件,它用来产生日志消息。产生的日志消息并不直接显示,还要预先经过Layout的格式化出来后才会输出。

Logger提供了多种方式来记录一个日志消息,你可以在你的应用程序里创建多个Logger,每个实例化的Logger对象都被log4net框架作为一个命名实体(named entity)来维护。这就意味着为了重用Logger对象,你不必将它在不同的类或对象之间传递,只需要用它的名字作为参数调用就可以了。Log4net框架使用继承体系,继承体系类似于.NET中的名字空间,也就是说,如果哦有两个logger,分别被定义为a.b.c 和a.b,那么我就说a.b是a.b.c的祖先。每一个Logger都集成了祖先的属性。

Logger框架定义了一个ILog接口,所有的logger类都必须实现这个接口。如果哦你想实现一个自定义的logger,你必须首先实现这个接口。

ILog接口的定义如下:

public interface Ilog

      void Debug(object message);

      void Info(object message);

      void Warn(object message);

      void Error(object message);

      void Fatal(object message);

//以上每个方法都有一个重载的方法,用来支持异常处理。重载方法如下所示:

void Debug(object message,Except ex);

void Info(object message,Except ex);

void Warn(object message,Except ex);

void Error(object message,Except ex);

void Fatal(object message,Except ex);

//Boolean属性用来检查Logger的日志级别,如下所示:

bool isDebugEnabled;

bool isInfoEnabled;

bool isWarngEnabled;

bool isErrorEnabled;

bool isFatalEnabled;

Log4net框架定义一个叫LogManager的类,用来管理所有的logger对象。他有一个GetLogger()静态方法,用我们提供的名字参数来检索已经存在Logger对象(保存在配置文件中)。如果框架里面不存在该Logger对象,它也会为我们创建一个Logger对象。代码如下所示:

Log4net.Ilog log = log4net.LogManager.GetLogger(LoggerName);

通常来说,我们会为类的类型为参数调用GetLogger(),以便跟踪我们在进行日志记录的类,传递类的类型可以用typeof(ClassName)方法来获得,或者可以用如下的反射方法来获得:

System.Reflection.MethodBase.GetCurrentMethod().DeclaringType,尽管符号长了一些,但是后者可以用于一些场合,比如获去调用方法的类的类型。

1.1.1 日志级别

正如在ILog的接口中看到的一样,有五中不同的方法可以跟踪一个应用程序。事实上这五中方法是运作在Logger对象设置的不通日志优先级别上。这几种不通的级别是作为常量定义在log4net.spi.Level类中。你可以在程序中使用任何一种方法。但是在最后的发布中,你也许不想让所有的代码来浪费你的cpu周期,因此,框架提供了7中级别和对象的Boolean属性来控制日志的记录的类型。

表1-1 Logger的日志级别

级别

允许方法

Boolean属性

优先级别

OFF

拒绝所有

 

Height

FATAL

Void Fatal(…);

bool isFatalEnabled

 

ERROR

VoidError(…);

bool isErrorEnabled

 

WARN

Void Warn (…);

bool isWarnEnabled

 

INFO

Void Info(…);

bool is InfoEnabled

 

DEBUG

VoidDebug(…);

bool isDebugEnabled

 

ALL

允许所以

 

Lowest

在log4net框架里,通过设置配置文件,每个日志对象都被分配一个日志优先级别,如没有给一个日志对象显式地分配一个级别,那么改对象会试图从他的祖先继承一个级别的。

ILog接口的每个方法都有一个预先定义好了的界别。正如表1-1看到的,ILog的Info()方法具有INFO级别。同样的,以此类推,Error()方法具有ERROR级别。当我们使用以上任何一种方法时,log4net框架会检查日志对象logger的级别和方法的级别。只有当方法的级别高于日志级别时,日志请求才会被接受并执行。

1.2   Respository

Respository主要用于负责日志对象组织结构的维护。在log4net的以前版本中,框架仅支持分等级的组织结构(hierarchical organization)。这种等级结构本质上是库的一个实现,并且定义在log4net.Respository.Hierarchy名字空间中。要实现一个Respository,需要

实现log4net.Respository.ILoggerRespository接口。但是通常并不是直接实现该接口,而是以log4net.Respository.LoggerRespositorySkeleton为基类继承体系库(hierarchical respository)则由log4net.Respository.Hierarchy.Hierarchy类实现。

    如果你是log4net框架的使用者,而非扩展者,那么你几乎不会在你的代码中用到Respository的类。相反的,你需要用到LogManager类来自动管理库和日志对象。

1.3  Appender

一个好的日志框架应该能够产生许多目的地的输出。如输出控制台,保存文件,或者存入数据库等。Log4net能够很好的满足这些要求。它是使用一个叫做Appender的组件来定义输出介质。正如名字所示,这些组件把他们附加到Logger日志组件上并将输出传递到输出流中。你可以把多个Appender组件附加到一个日志对象上。Log4net框架提供了几个Appender组件。

1.4  Appender Filters

一个Appender对象缺省地将所有的日志时间传递到输出流。Appender的过滤器(Appender Filters)可以按照不同的标准过滤日志事件。在log4net.Filter的名字控件下已经有几个预定义的过滤器。使用这些过滤器,你可以按照日志级别范围过滤日志时间,或者按照某个特殊的字符串进行过滤。你可以在API的帮助文件中发现更多有关Filter的信息。

1.5 Layout

Layout组件用于向用户显示最后经过格式化的输出信息。输出信息可以一多种格式显示,主要依赖与我们采用的layout组件的类型。可以是线性的或者XML文件。Layout组件和一个Appender组件一起工作哦。API帮助手册中有关于不通Layout组件的列表。一个Appender对象,只能对象一个Layout对象。要实现你自己的Layout类,你需要从log4net.Layout.LayoutSkeleton类继承,它实现了ILayout接口。

2           定义配置文件

配置信息可以放在如下几中形式文件的一种中。

1.在程序的配置文件里,如AssemblyName.Config 或 web.config.

2.在自己的文件里,文件名可以自取。

Log4net框架会在相对于AppDomain.CurrentDomain.Base.Directory属性定义的目录路径下查找配置文件。框架在配置文件里要查找的唯一表示是<log4net>标签。一个完整的配置文件(命名为:Log.config)的例子如下:

<?xml version="1.0" encoding="utf-8" ?>

<configuration>

  <configSections>

    <section name ="log4net" type ="log4net.Config.Log4NetConfigurationSectionHandler,log4net-net-1.0"/>

  </configSections>

 

  <log4net>

 

    <logger name="ManagerLog">

      <level value="ALL"/>

      <appender-ref ref ="LogFileAppender"/>

      <appender-ref ref ="ADONetAppender"/>

    </logger>

 

    <!--<root>

      <level value="ALL" />

      <appender-ref ref="ADONetAppender"/>

    </root>-->

 

    <appender name="LogFileAppender" type="log4net.Appender.RollingFileAppender">

      <file value="log.log"/>

      <appenderToFile value="true"/>

      <rollingstyle value="Date"/>

      <datePattern value="yyyyMMdd"/>

      <encoding value="utf-8"/>

      <param name="MaxSizeRollBackups" value="5" />

      <param name="MaximumFileSize" value="10MB" />

 

      <layout type="log4net.Layout.PatternLayout">

        <conversionPattern value="%d [%-5level]: %m%n" />

      </layout>

 

      <!--<filter type="log4net.Filter.LevelRangeFilter">

        <levelMin value ="OFF"/>

        <levelMax value ="ALL"/>

      </filter>-->

    </appender>

 

    <appender name ="ADONetAppender" type="log4net.Appender.ADONetAppender">

      <bufferSize value ="10"/>

      <connectionType value ="System.Data.SqlClient.SqlConnection,System.Data,Version=1.0.3300.0,Culture=neutral,publicKeyToken=b77a5c561934e089"/>

      <connectionString value="server=SUNLIKE\SQLEXPRESS;database=blank;user id = sa;password = sa;timeout=300;"/>

      <commandText value="INSERT INTO [Log] ([Date],[Thread],[Level],[Logger],[Message],[Exception]) VALUES (@log_date, @thread, @log_level, @logger, @message, @exception);"/>

 

      <parameter>

        <parameterName value="@log_date"/>

        <dbType value ="DateTime"/>

        <layout type ="log4net.Layout.RawTimeStampLayout"/>

      </parameter>

 

      <parameter>

        <parameterName value="@thread"/>

        <dbType value ="String"/>

        <size value ="255"/>

        <layout type ="log4net.Layout.PatternLayout">

          <conversionPattern value ="%thread"/>

<!--<conversionPattern value ="%t"/>-->

</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 ="4000"/>

        <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>

 

  </log4net>

</configuration>

 

如果Log.config存放在debug目录下,需要在Assembly.cs 末尾添加代码:

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

如果Log.config存放在其他目录下,则需要在Assembly.cs 末尾添加代码:

[assembly: log4net.Config.XmlConfigurator(Watch = true)](注:如果在app.config 或者web.config 只要写这行代码即可)

还需要在Program.cs中添加代码(确保找到配置文件):

string path = @" ";//存放Log.config的路径

FileInfo file = new FileInfo(path+ @"Log.config");

if (File.Exists(file.ToString()))

  {

      log4net.Config.XmlConfigurator.Configure(file);

     }

    else

       {

           throw new Exception("log4net日志配置文件未找到");

       }

在程序中自定定义一个类ManagerLog类,对log4net的方法进行重写。

public class ManageLog

    {

        #region 字段定义

        private static ILog logEntry = LogManager.GetLogger("ManagerLog");  

       //ManagerLog 与配置文件中的Logger节中name属性的值保持一致

    // private static object objectMultx = new object();

        //private static string logname = "log";

        #endregion

       

        #region 公共接口

        /// <summary>

        /// 输出程序调试信息

        /// </summary>

        /// <param name="message">输出信息</param>

        public static void Debug(string message)

        {

            logEntry.Debug(message);

        }

        /// <summary>

        /// 输出程序错误信息

        /// </summary>

        /// <param name="message">输出信息</param>

        public static void Info(string message)

        {

            logEntry.Info(message);

        }

        /// <summary>

        /// 输出程序错误信息

        /// </summary>

        /// <param name="message">输出信息</param>

        public static void Warn(string message)

        {

            logEntry.Warn(message);

        }

        /// <summary>

        /// 输出程序警告信息

        /// </summary>

        /// <param name="message">输出信息</param>

        public static void Error(string message)

        {

            logEntry.Error(message);

        }

        /// <summary>

        /// 输出程序致命错误信息

        /// </summary>

        /// <param name="message">输出信息</param>

        public static void Fatal(string message)

        {

            logEntry.Fatal(message);

        }

        #endregion

在需要写日志的地方加上相应的调用语句,如:

ManageLog.Debug("记录时间……");

 

2.1 布局样式:

Class

Description

ExceptionLayout

只呈现日志事件中异常的文本信息

Layout2RawLayoutAdapter

适应于Ilayout接口到IRawLayout

LayoutSkeleton

扩展这个抽象类来创建自定义的布局格式

PatternLayout

可以通过类型字符串来配置的布局

PatternLayout.ConverterInfo

把转换器名字映射为转换器类型的包装类

RawLayoutConverter

IrawLayout接口的类型转换器

RawPropertyLayout

从日志事件中提取属性值

RawTimeStampLayout

从日志事件中提取日期

RawUtcTimeStampLayout

从日志事件中提取日期

SimpleLayout

很简单的布局

XmlLayout

把日志事件格式化为XML元素的布局

XmlLayoutBase

把日志事件格式化为XML元素的布局

XmlLayoutSchemalLog4j

把日志事件格式化为与log4j结构兼容的XML元素布局

2.2  一些说明

(一)log4配置说明

log4net的配置可以放在应用程序的默认配置文件中(app.config或web.config),也可以再你自己的配置文件中。(如果log4net的配置不是放在应用程序的配置文件里,而是在自己定义的文件里,<configSection>节点里的<section>节点是不需要的。

(二)节点分析

在配置章节中,定义section节点。节点名称为:须为log4net,且大小写敏感。

<configSections>

    <section name="log4net"

             type="log4net.Config.Log4NetConfigurationSectionHandler" />

  </configSections>

 

(三)Log4net章节内容

debug 可选,取值是true或false,默认是false。设置为true,开启log4net的内部调试。

update 可选,取值是Merge(合并)或Overwrite(覆盖),默认值是Merge。设置为Overwrite,在提交配置的时候会重置已经配置过的库。 

threshold 可选,取值是repository(库)中注册的level,默认值是ALL。

支持的子元素:

·appender  0或多个

·logger 0或多个

·renderer 0或多个

·root 最多一个

·param 0或多个

(四)两个Appenders(输出源)

定义日志的输出方式,只能作为 log4net 的子元素。name属性必须唯一,type属性必须指定

支持的属性:

name 必须的,Appender对象的名称

type 必须的,Appender对象的输出类型

支持的子元素:

·appender-ref 0个或多个,允许此appender引用其他appender,并不是所以appender类型都支持。

·filter 0个或多个,定义此app使用的过滤器。

·layout 最多一个。定义appender使用的输出格式。

·param 0个或多个, 设置Appender类中对应的属性的值。

 

·LogFileAppender

节点日志文件输出。type="log4net.Appender.FileAppender"

·ConsoleAppender

节点控制台输出。type="log4net.Appender.ConsoleAppender"

 

(五)一个root

根logger,所有其它logger都默认继承它。root元素没有属性。

支持的子元素:

·appender-ref 0个或多个,要引用的appender的名字。

·level 最多一个。 只有在这个级别或之上的事件才会被记录。

·param 0个或多个, 设置一些参数。

<root>

      <level value="WARN" />

      <appender-ref ref="LogFileAppender" />

      <appender-ref ref="ConsoleAppender" />

    </root>

(六)Logger

支持的属性:

name 必须的,logger的名称

additivity 可选,取值是true或false,默认值是true。设置为false时将阻止父logger中的appender。

支持的子元素:

·appender-ref 0个或多个,要引用的appender的名字。

·level 最多一个。 只有在这个级别或之上的事件才会被记录。

·param 0个或多个, 设置一些参数。

 

<logger name="testApp.Logging">

      <level value="DEBUG"/>

    </logger>

(七)Layout

布局,只能作为<appender>的子元素。

支持的属性:

type 必须的,Layout的类型

支持的子元素:param 0个或多个, 设置一些参数。

(八)Filter

过滤器,只能作为<appender>的子元素。

 

支持的属性:

type 必须的,Filter的类型

支持的子元素:param 0个或多个, 设置一些参数。

(九)Param

<param>元素可以是如何元素的子元素。

 

支持的属性:

name 必须的,取值是父对象的参数名。

value 可选的,value和type中,必须有一个属性被指定。value是一个能被转化为参数值的字符串。

type 可选的,value和type中,必须有一个属性被指定。type是一个类型名,如果type不是在log4net程序集中定义的,就需要使用全名。

支持的子元素:param 0个或多个, 设置一些参数

2.3  模式转化

%m(message)输出日志消息

%n(newline)换行

%d(datetime)输出当前语句运行的时刻

%r(runtime)输出当前语句的运行时刻

%t(thread id)当前语句所在的线程ID

%p(priority)日志的当前优先级别,DEBUG INFO ……

%c(class)当前日志对象的名称

%L 输出语句所在的行号

%F 输出语句所在的文件名

%-数字 表示该项的最小长度,如果不够,用空格填充

结束语

    通过这两天的学习对log4net组件的配置有了一定的了解,能进行简单的日志输出,不仅能够在console显示,也可以导入到文本文件里,还可以导入到数据库中。方便简单,在开发中是一个很不错的助手。在学习的过程中也发现不少问题,比如做一个控件,该控件有写日志的功能,日志写入到sql server 2005中,仅当该控件销毁之后,才能一次写入数据库,即如果该控件还在活动,在数据库中是查不出刚刚添加的日志记录。具体原因不太清楚,也没有深究,我估计日志是当成一个事物来处理了。另外还有一个问题,就是目前还没有找到一种行之有效的方法写入oracle10g 或oracle 11g的方法。如果有朋友看到该疑问,请帮忙指正和赐教。网上也有很多资料,本篇篇文章写的比较肤浅,是参照百度文库的一篇文章和csdn一些n人的博客,结合自己的实际开发,总结而成,如有文章中有什么不妥之处,还请指正。不胜感激。

 

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值