Log4Net 学习与使用

一、什么是Log4Net

  Log4Net库是Apache log4j框架在Microsoft .NET平台的实现,是一个帮助程序员将日志信息输出到各种目标(控制台、文件、数据库等)的工具。

  用户可以从http://logging.apache.org/log4net/下载log4net的源代码。解压软件包后,在解压的src目录下将log4net.sln载入Visual Studio .NET,编译后可以得到log4net.dll。用户要在自己的程序里加入日志功能,只需将log4net.dll引入工程即可。

二、具有什么特征

  • 支持多数框架
  • 可输出日志到多种目标
  • 层级日志体系
  • 可使用XML配置
  • 可动态配置
  • 记录上下文信息
  • 被检验过的体系
  • 模块化和可扩展化设计
  • 灵活、高性能

三、Log4Net的结构

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

  

  3.1 Logger记录器

  3.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都继承了祖先的属性。

  Log4net框架定义了一个ILog接口,所有的logger类都必须实现这个接口。如果你想实现一个自定义的logger,你必须首先实现这个接口。你可以参考在/extension目录下的几个例子。

  ILog接口的定义如下:

public interface ILog : ILoggerWrapper
{
    void Debug(object message);
    void Debug(object message, Exception exception);
    void DebugFormat(string format, params object[] args); 
    void DebugFormat(string format, object arg0); 
    void DebugFormat(string format, object arg0, object arg1); 
    void DebugFormat(string format, object arg0, object arg1, object arg2); 
    void DebugFormat(IFormatProvider provider, string format, params object[] args);

    void Info(object message);
    void Info(object message, Exception exception);
    void InfoFormat(string format, params object[] args);
    void InfoFormat(string format, object arg0); 
    void InfoFormat(string format, object arg0, object arg1); 
    void InfoFormat(string format, object arg0, object arg1, object arg2); 
    void InfoFormat(IFormatProvider provider, string format, params object[] args);

    void Warn(object message);
    void Warn(object message, Exception exception);
    void WarnFormat(string format, params object[] args);
    void WarnFormat(string format, object arg0); 
    void WarnFormat(string format, object arg0, object arg1); 
    void WarnFormat(string format, object arg0, object arg1, object arg2); 
    void WarnFormat(IFormatProvider provider, string format, params object[] args);

    void Error(object message);
    void Error(object message, Exception exception);
    void ErrorFormat(string format, params object[] args);
    void ErrorFormat(string format, object arg0); 
    void ErrorFormat(string format, object arg0, object arg1); 
    void ErrorFormat(string format, object arg0, object arg1, object arg2); 
    void ErrorFormat(IFormatProvider provider, string format, params object[] args);

    void Fatal(object message);
    void Fatal(object message, Exception exception);
    void FatalFormat(string format, params object[] args);
    void FatalFormat(string format, object arg0); 
    void FatalFormat(string format, object arg0, object arg1); 
    void FatalFormat(string format, object arg0, object arg1, object arg2); 
    void FatalFormat(IFormatProvider provider, string format, params object[] args);

        
    bool IsDebugEnabled { get; }
    bool IsInfoEnabled { get; }
    bool IsWarnEnabled { get; }
    bool IsErrorEnabled { get; }
    bool IsFatalEnabled { get; }
}

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

ILog log = LogManager.GetLogger("application-log");
     
log.Info("Application Start");
log.Debug("This is a debug message");
     
if (log.IsDebugEnabled)
{
    log.Debug("This is another debug message");
}

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

  System.Reflection.MethodBase.GetCurrentMethod().DeclaringType

  尽管符号长了一些,但是后者可以用于一些场合,比如获取调用方法的类(class)的类型(type)。

   3.1.2 日志的级别

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

  Level有以下几种取值

级别 允许的方法 Boolean属性 优先级别
OFF     Highest
FATAL void Fatal(...); bool IsFatalEnabled;  
RROR void Error(...); bool IsErrorEnabled;  
WARN void Warn(...); bool IsWarnEnabled;  
INFO void Info(...); bool IsInfoEnabled;  
DEBUG void Debug(...); bool IsDebugEnabled;  
ALL     Lowest

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

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

  举例说明,当你创建了一个日志对象,并且把他的级别设置为INFO。于是框架会设置日志的每个Boolean属性。当你调用相应的日志方法时,框架会检查相应的Boolean属性,以决定该方法能不能执行。如下的代码:

Logger.Info("message");
Logger.Debug("message");
Logger.Warn("message");

  对于第一种方法,Info()的级别等与日志的级别(INFO),因此日志请求会被传递,我们可以得到输出结果”message”。

  对于第二种方法,Debug()的级别低于日志对象logger的日志级别(INFO),因此,日志请求被拒绝了,我们得不到任何输出。同样的,针对第三行语句,我们可以很容易得出结论。

  ALL和OFF。ALL表示允许所有的日志请求。OFF是拒绝所有的请求。

  你也可以显式地检查Logger对象的Boolean属性,如下所示:

if (logger.IsDebugEnabled)
{
    Logger.Debug("message");
}

   

  3.2 Repository库
  Repository主要用于负责日志对象组织结构的维护。在log4net的以前版本中,框架仅支持分等级的组织结构(hierarchical organization)。这种等级结构本质上是库的一个实现,并且定义在log4net.Repository.Hierarchy 名字空间中。要实现一个Repository,需要实现log4net.Repository.ILoggerRepository 接口。但是通常并不是直接实现该接口,而是以log4net.Repository.LoggerRepositorySkeleton为基类继承。体系库 (hierarchical repository )则由log4net.Repository.Hierarchy.Hierarchy类实现。
  如果你是个log4net框架的使用者,而非扩展者,那么你几乎不会在你的代码里用到Repository的类。相反的,你需要用到LogManager类来自动管理库和日志对象。

 

   

  3.3 Log4Net Appender(附着器)
  一个好的日志框架应该能够产生多目的地的输出。比如说输出到控制台或保存到一个日志文件。log4net 能够很好的满足这些要求。它使用一个叫做Appender的组件来定义输出介质。正如名字所示,这些组件把它们附加到Logger日志组件上并将输出传递到输出流中。你可以把多个Appender组件附加到一个日志对象上。

  Log4net框架提供了几个Appender组件,关于log4net提供的Appender组件的完整列表可以在log4net框架的帮助手册中找到。有了这些现成的Appender组件,一般来说你没有必要再自己编写了。但是如果你愿意,可以从log4net.Appender.AppenderSkeleton类继承。

  更多Appender点击 这儿

  

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

  过滤器通常有以下几种:

  • DenyAllFilter 阻止所有的日志事件被记录
  • LevelMatchFilter 只有指定等级的日志事件才被记录
  • LevelRangeFilter 日志等级在指定范围内的事件才被记录
  • LoggerMatchFilter 与Logger名称匹配,才记录
  • PropertyFilter 消息匹配指定的属性值时才被记录
  • StringMathFilter 消息匹配指定的字符串才被记录

  

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

  一个Appender只能有一个Layout。

  最常用的Layout应该是经典格式的PatternLayout,其次是SimpleLayout,RawTimeStampLayout和ExceptionLayout。然后还有IRawLayout,XMLLayout等几个,使用较少。Layout可以自己实现,需要从log4net.Layout.LayoutSkeleton类继承,来输出一些特殊需要的格式,在后面扩展时就重新实现了一个Layout。

  • SimpleLayout简单输出格式,只输出日志级别与消息内容。
  • RawTimeStampLayout 用来格式化时间,在向数据库输出时会用到。样式如“yyyy-MM-dd HH:mm:ss“
  • ExceptionLayout需要给Logger的方法传入Exception对象作为参数才起作用,否则就什么也不输出。输出的时候会包含Message和Trace。
  • PatterLayout使用最多的一个Layout,能输出的信息很多
posted @ 2016-06-22 11:05  a boy  阅读(607)  评论(0)    收藏  举报