原文:http://www.cnblogs.com/maxliu/archive/2012/08/03/2621088.html
最近项目需要一个日志工具来跟踪程序便于调试和测试,为此研究了一下.NET日志工具,本文介绍了一些主流的日志框架并进行了对比.发表出来与大家分享.
综述
所谓日志(这里指程序日志)就是用于记录程序执行过程中的信息,以便开发、测试和支持人员在调试或测试时利用这种技术来快速分析和定位程序中的问题和缺陷。日志通常将程序执行中的信息以文本的形式写入日志文件或将程序数据发送到监视器(比如说数据库、远端计算机、邮箱、网页等)。高级一些的日志工具还支持对一些复杂的数据结构、调用栈、线程等进行实时监控和记录。
大多数.NET的日志框架有着一些共同的概念和特性。根据作用来分主要有以下组件或概念:记录器(Logger)、监视器/目标(Monitor/Target)、包装器(Wrapper)、过滤器(Filter)、布局(Layout)、严重性级别(Severity)。
1.记录器:日志的对象,可以同时连接一个或多个不同的监视器,记录各种不同的消息和信息。
2.监视器:用于存储和显示日志消息的媒介,有多种存在形式。如一般的文本文件、数据库、网络、控制台、邮箱等。
3.包装器:用于制定日志记录的方式。如:同步/异步记录,(出错时)回滚记录。
4.过滤器:用于根据严重性级别来过滤和忽略某类消息,只记录特定级别的日志消息。
5.布局:用于格式化输出。定义输出项和输出格式。
6.严重性级别:是对消息的分类,严重性级别表示消息的严重程度。也是过滤器的过滤依据。如:调试(DEBUG)、消息(INFO)、警告(WARN)、错误(ERROR)、严重错误(FATAL)严重性依次增强。
与上述对应的是一般的日志框架会提供的一些基本特性和功能:
1.记录简单的文本消息。
2.消息级别的过滤。
3.允许多个监视器。
4.记录消息种类和会话。
5.根据时间或大小将文件分割。
6.通过配置文件来控制日志,与代码分离。
当然还会有些高级功能,如线程的安全以及同步或异步,数据结构或对象的记录,可视化的日志查看器和分析器等等。
现在,已经有很多成熟的.NET日志工具,免费的、收费的、开源的都有。 一些主流的日志工具和框架有:NLog、log4net、Enterprise Library、ObjectGuy Framework等。接下来主要介绍一下ObjectGuy Framework、log4net、NLog这三种日志框架。
ObjectGuy Framework
一种轻量级的.NET日志工具。能提供基本的日志特性并具有很好的扩展性。它是一种纯代码控制的日志工具,小巧便捷,语法简单直接,很容易上手和使用。
ObjectGuy Framework中一般的logger只能对应一种监视器,而且都有相对应的类,这些类都是继承自logger这个抽象基类。因此实例化一个logger很简单,只要调用那个类即可。如TextWriterLogger、FileLogger、SerialSocketLogger分别对应监视器为控制台、文件、网络的logger。当然如果你想绑定多个监视器,ObjectGuy提供了CompositeLogger这个类,并有相应的AddLogger方法可以将上述logger子类加入到CompositeLogger中与其绑定,这样当CompositeLogger进行记录时,其加入的普通logger都将同时自动记录。ObjectGuy还有一个InsistentLogger类,顾名思义它是一个帮助的logger。当其绑定的主logger发生异常时,该InsistentLogger会自动启动尝试进行记录。
ObjectGuy 中的消息分为7种严重性级别:Debug, Info, Status, Warning, Error, Critical, Fatal。默认级别为Debug。每一种级别都有对应的消息记录方法LogXXX。消息过滤也很简单,只要设置一下logger的SeverityThreshold的级别,那么所有级别低于SeverityThreshold的消息将被忽略。关于消息的格式化输出,ObjectGuy提供了LogEntryFormatter类来制定相应的格式化。由于ObjectGuy中的所有特定logger都是继承自Logger这一抽象类,因此构造自定义logger也很简单,只要继承该抽象类并重写相应的方法即可。下图为ObjectGuy中的类层次结构:
可以看出ObjectGuy是一个非常简单易用的日志工具,它可以满足基本的日志要求和特性而且有很好的扩展性。但是由于ObjectGuy非常简洁,一些高级特性没能被提供。其实ObjectGuy好比是编辑工具中的记事本,简便、快捷。如果只是使用一些基本特性而对word又不是死磕的话,ObjectGuy还是一个非常不错的选择。(PS:ObjectGuy是一个付费工具,非商业版只要5美元。主页:http://www.theobjectguy.com/dotnetlog/)
log4net
log4net是Apache上的一个开源项目,是基于非常成功的log4j(log for java)架构完成的。其实是log4j的.NET版本,但又结合了.NET的特性。log4net提供了很多功能,除了一些基本特性外,log4net支持配置文件控制。程序运行时只要修改配置文件就能对日志进行控制,实现和代码的分离。另外log4net支持很多.NET框架,从1.0到4.0中的各种版本,同时也支持Mono(跨平台)。log4net中的监视器(Target)要比ObjectGuy丰富得多,有20种之多。
log4net中logger的使用不像ObjectGuy那样直接。创建一个logger实例需要通过LogManager的GetLogger方法来完成。由于log4net中的logger是和类对应的(类级别日志,class-level logging),因此需要类名或类的类型typeof(类名)作为GetLogger的参数来获取该类的logger的一个引用。相同的类名(指完整类层次名:namespace.className)指向同一个logger。在log4net中很特别的一点是logger的层次关系,一个logger可以有祖先logger和子logger,他们之间存在一些继承关系。主要有两方面:
1.严重性级别的继承:log4net中有All、Debug、Info、Warn、Error、Fatal、Off七种级别,严重程度和优先级依次上升。若当前logger的级别为空(未赋值),则其继承父logger的严重性级别。
2.监视器(log4net中称Appender)的继承:也叫监视器的可加性。当前logger的监视器如果为空,则继承祖先logger的监视器。若不为空,则当前logger的监视器会自动添加祖先logger的监视器。也即祖先监视器会继承给子监视器,这种特性依赖Additivity的值。其默认为真。可以看出与ObjectGuy不同的是,log4net中的logger可以任意绑定多个监视器,只要定义相应的Appender然后添加即可。
log4net中存在一个根logger(root logger),它是所有logger的祖先,严重性级别默认为Debug。其他的logger则会依据完整类层次名称来区分祖先和后代关系。例如:对应于X.Y的logger的父亲为对应于X的logger。当然只有这些logger被实例化之后这种关系才会生效。log4net中还提供对象呈现器(Object Renderers),它可以提供一种用户自定义的对象呈现规则。当该对象被记录时,对应的对象呈现器会自动触发。
log4net的另一个特色是它的配置文件,配置文件可以像代码一样对logger进行各种设置。而且可以在程序运行时进行方便的进行修改从而得到需要的日志记录。配置文件是XML格式,因此有很好的标记性,很容易书写。配置文件的标签包含大量API中logger相关的类。如:root(根logger)、logger、appender、layout、renderer、filter等。完全能够像代码一样对程序中的日志进行设置和管理。
综上所述,log4net能够提供非常多的特性支持,相比ObjectGuy而言有过之无不及。而且有很多第三方的可视化日志查看器和分析器支持log4net使其更加直观。然而log4net的架构也很复杂,因此使用起来没有ObjectGuy那样简单直观。另外由于log4net不能提供异步记录,如果插入的代码很多,势必会影响应用程序的性能。(PS:log4net的更新非常缓慢,维护人员不多。从1.2.10版本到1.2.11版本花了4年时间(2006-2011)。主页:http://logging.apache.org/log4net/)
NLog
NLog和log4net非常相似,都是开源工程,都支持.NET框架和跨平台,都有配置文件,都有丰富的监视器等等。可以说他们提供的特性绝大部分都是相同的。不过差别还是有的,下面主要讲一下两者的不同之处。
和log4net一样,NLog中的logger也是类级别的。实例化一个logger除了像log4net一样用LogManager.GetLogger("ClassName")也可以直接用LogManager.GetCurrentClassLogger()获取当前类的logger。与log4net不同,NLog中的logger没有层次结构,因此也不存在继承等特征,所以NLog中logger的严重性级别和监视器(target)必须要定义。这一点跟ObjectGuy较像,简单直观。严重性级别上,NLog有Debug、Trace、Info、Warn、Error、Fatal六种。除了监视器,NLog中多了一层包装器(Wrapper),顾名思义它是用来包装监视器的。NLog提供了很多包装器。如AsyncWrapper:异步包装器,使logger可以异步地将记录写入包装器里面的监视器,从而提高应用程序的响应速度,保证应用程序的性能不受太大影响;FallbackGroup:回滚组,当logger出现错误时回滚。由此可见NLog是支持异步和回滚的,这使得NLog的性能比log4net要好。至于配置文件方面,两者只是标签和属性不同而已。
其实NLog更像是ObjectGuy和log4net的结合,既有ObjectGuy的简单易用,又有log4net的绝大部分强大特性。而且NLog支持异步记录,使得NLog的整体性能要优于log4net。NLog也有一些第三方图形查看器和分析器。同时NLog更新频繁,有很好的维护,应该是一个很不错的选择(个人推荐)。由于NLog使用起来非常方便(无论是通过代码还是配置文件),这里不做过多介绍,详细信息参看NLog主页:http://nlog-project.org/。
最后附上一些主流.NET日志工具的综合性能比较:
(PS:SmartInspect为纯商业.NET日志工具,Enterprise Library为微软推出的日志库。)