Fork me on GitHub

通用日志

一、背景
为软件开发提供一个现成的、定义良好的、可扩展的日志设施。所谓"现成的"意思为软件开发可以即刻使用,包括API文档、使用实例和库;"定义良好的"表示项目提供良好的使用接口和具有优秀的内部设计;可扩展的意味用户可以进一步扩展功能。
关心软件日志的主要有三类用户:开发人员、系统管理人员和系统运行单位。三类用户各有各的日志需求:
l         开发人员在写代码的时候经常要输出程序的内部状态,目的可以是开发时的调试,或运行时的维护。
l         系统管理人员需要获取软件的状态数据以便进一步配置系统使其正常和高效运行。
l         系统运行单位需要软件保存操作日志以便例行检查或秋后算账。
虽然三类用户各有各的需求,对于日志设施来说可以归结为以下功能特性:
1.        日志操作:日志功能是指基本的日志登记操作,是软件系统和日志设施之间的简单接口。软件系统一般只向这些功能传递应用日志信息。
2.        级别:级别是指软件系统可以分级别地进行日志登记操作。日志设施的级别特性表现为日志操作和设施配置两部分。日志操作的级别表现为软件系统可以指定某次日志登记的级别,设施配置的级别规定了有效的日志操作的最低级别。如果软件系统中某个日志操作的级别低于配置指定级别,这个日志操作是无效的,既不会发生日志登记行为。日志设施的级别性对于开发人员来说非常有用,它一方面有助于开发人员调式系统时了解详尽的系统状态信息,另一方面有利于开发人员对运行时软件系统故障的诊断和问题解决。而且系统从开发状态到运行状态转变时,开发人员插入到软件中的调式日志代码不需要删除,只需要提高日志的配置级别,并且最终使得程序员对System.Console.Write的嗜好已成为过去。
3.        日志目标多样性:日志目标的多样性指日志可以被登记到多个日至设备,比如文件、控制台、数据库、邮件系统等。日志目标多样性使得软件系统可以按照某种标准把日志输出到不同的设备上,比如调试用的日志一般可以输出到控制台,例行检查的日志可以保存到数据库中,系统出错的日志可以发通过邮件系统发到管理员或维护员邮箱。
4.        日志格式:作为一种设施,除了登记软件系统指定的应用日志信息之外,日志设施往往还提供一些额外的系统日志信息,比如系统时间,日志发生的上下文等,而且能对所有的日志信息进行格式编排。日志格式一般在日志设施的配置文件中设置,有助于节省软件系统调用日志操作接口时的编程负担,降低接口的复杂度。
值得注意的是软件系统到底往日志设备中记录什么东西,也就是说应用日志信息的具体内容由运用日志设施的软件系统决定,与日志设施没有直接关系。
二、解决方案
   目前有许多日志的实现,像log4net,nlog,logging application block,避免对某一实现的依赖就是通用日志所要做的事情。在Castle项目和Spring.NET中的实现是不一样的,Castle所采用通用日志接口定义于框架核心Castle.Core.LoggingSpring.NET采用单独的程序集方式。Spring.NET的日志叫做“Common.Logging”,应该是移植自JCL(Jakarta Commons Logging)。从使用上来说Spring.NET的日志更为通用。
     下面介绍一下Spring.NETCommon.Logging, 你项目中没有使用Castle,Spring.NET也一样可以使用这样的一个通用日志接口,而且很容易就和log4net,nlog,logging application block集成。
      commons-logging是个日志设施通用实现,虽然提供了对应用编程接口的缺省实现(SimpleLog,但是主要意图还是希望封装强大的日志系统。明白了这一点,我们就面临这样的场景:一边有现成的日志系统,如log4net,nlog,logging application block;另一边有易用的使用界面。我们需要一种设计能使这两边协调工作,设计模式-适配模式是我们的理想选择。

 

既然commons-logging是一个通用接口,它的实现就不能和某个具体的日志系统绑死。我们需要一种能在代码外实现这种绑定的设计。一般地我们用gang of four creational模式类中的一种模式来创建实现某个接口的类的实例,commons-logging采用了工厂方法模式来选择具体的日志实现。下表引入工厂方法模式描述。

 

common logging 提供简单的日志实现,目前提供的是无输出,控制台,Trace(以上三种实现,在配置文件factoryAdapter type attribute中有简写方式NOOP,CLOSE,TRACE. 简单的配置如下:

 <configSections>

 
<sectionGroup name="common">
 
<section name="logging" type="Common.Logging.ConfigurationSectionHandler, Common.Logging" />
 
</sectionGroup>

 
</configSections>

 
<common>
 
<logging>
 
<factoryAdapter type="Common.Logging.Simple.ConsoleOutLoggerFactoryAdapter, Common.Logging">
 
<arg key="showLogName" value="true" />
 
<arg key="showDataTime" value="true" />
 
<arg key="level" value="DEBUG" />
 
<arg key="dateTimeFormat" value="yyyy/MM/dd HH:mm:ss:fff" />
 
</factoryAdapter>
 
</logging>
 
</common>
和Log4Net搭配使用也很容易的,加入如下配置就可以了:
<factoryAdapter type="Common.Logging.Log4Net.Log4NetLoggerFactoryAdapter, Common.Logging.Log4Net">
 
<!-- choices are INLINE, FILE, FILE-WATCH, EXTERNAL-->
 
<!-- otherwise BasicConfigurer.Configure is used -->
 
<!-- log4net configuration file is specified with key configFile-->
 
<arg key="configType" value="INLINE" />
 
</factoryAdapter>
 
</logging>
log4net这两个版本(log4net 1.2.9和log4net1.2.10)的程序集都使用强命名,所以有两个分别针对log4net 1.2.9和log4net1.2.10有两个版本的实现。

.NET开源项目介绍及资源推荐:日志记录
posted @ 2007-12-30 11:02 张善友 阅读(...) 评论(...) 编辑 收藏