Log4net源码分析(二)

本文深入介绍了Log4Net的日志记录架构,涵盖了ILogger日志实体、日志结构ILoggerRepository、LogManager、ILoggerWrapper日志包装类等多个核心组件。此外,还详细解析了IAppender输出方式、IFilter过滤方案、ILayout消息格式定义等关键概念。


3 Log4net重点对象介绍

3.1 ILogger日志实体:

在Log4Net架构中,对日志的记录是以日志实体为单位的。它记录日志的最低级别(高于此基本的消息都可以记录),日志的名称,以及维护日志结构的库(Repository)。它包含记录日志的操作。但在扩展日志类实体时,一般不直接实现ILogger接口,而是继承Logger类,这是一个虚类。它除了实现接口ILogger外,也实现了IAppenderAttachable,以确保使自己可以被绑定到Appender上。一个日志实体可以绑定到一个或多个Appender上。由于框架支持分层级的组织结构,所以它有一个属性Parent,已建立与上层的关联。RootLogger继承自Logger,它表示根层节点。

3.2 日志结构ILoggerRespository:

日志的结构是层级结构,可选择子日志对象(通过属性Additivity)是否继承父对象的Appender,子对象和父对象在一个Hierarchy中。同时通过两种方式记录日志的层次关系,一种为子日志对象指定其父日志对象,另一种方式是通过日志的名称来记录:如果有两个logger,分别被定义为a.b.c和a.b,那么我们说a.b是a.b.c的祖先。

若某一个日志对象有个父节点,但是这个父节点却还没有被指定,这时就可以用一个临时节点来代替,ProvisionNode的作用就在于此。它是一个集合对象,继承自ArrayList,可以暂时在此保存它的所有自节点,以方便于以后指定一个ILogger对象来替换它。

ILoggerRespository类就像是Log4net的骨架,他支撑着整个Log4net的结构并管理着Log4net的各个部件。下面我们分析一下ILoggerRespository的功能以及工作原理:

ILoggerRespository类中维护着LevelMap,PluginMap分别是Level,Plugin对象以其名称为键的集合,,Rendermap是IObjectRender以其类型为键的集合。而Hierarchy中存储着已创建的ILogger的对象集合,此集合是以LoggerKey为键的映射。

ILoggerRespository中维护并存储着这些对象的集合,但它并不负责创建这些对象,而是把创建的工作委托给了XmlHierarchyConfigurator。它负责解析对Log4net的Xml(节点)配置。Hierarchy类不直接创建ILogger对象,而是通过ILoggerFactory对象来创建ILogger对象。在Hierarchy类中保存ILoggerFactory的一个默认实现:DefaultLoggerFactory。

3.3 LogManager

LogManager作为面向用户的接口,它是在启用配置文件后被应用程序调用来创建ILog对象的。我们知道ILog是继承自ILoggerWrapper,所以ILog对象也是对ILogger对象的封装,ILog暴露出的接口比ILogger对象接口更好理解,更好使用。但是最终在Log4net框架中操作的是ILogger对象,而用户看到的却是对ILog对象的操作,这中间又是如何关联的呢,或者说这其中的机制是什么呢?

在LogManager中有一个类型为WrapperMap的静态成员变量s_wrapperMap。我们先看看WrapperMap类,它被用来创建ILog对象,并维护ILogger对象与ILoggerWrapper对象的对应关系。它的映射关系是:

<Hashtable>

<key type=”ILoggerRepository”/>

<value type =”Hashtable”>

<Hashtable>

<key type=”ILogger”/>

<value type=”ILoggerWrapper”/>

</Hashtable>

</value>

</Hashtable>

这个类复杂对这个映射关系的维护,包括创建、获取及销毁。但是,ILoggerWrapper对象的创建工作却是通过代理委托出去了,在这里是委托给LogManager中的一个静态方法了:private static ILoggerWrapper WrapperCreationHandler(ILogger logger)。

3.4 ILoggerWrapper日志包装类:

日志包装类是对日志对象的包装,通过此接口可以获取它说包装的ILogger对象。ILog是ILoggerWrapper的子接口,它是Log4Net Framework的对外接口。框架使用者通过它可以对各种日志对象进行操作,写相应基本的日志等。

3.5 LoggerManager 工具类

LoggerManager 工具类被用来获取ILoggerRepository和ILogger对象。但它并不能直接创建和维护这些对象。所以它把创建ILoggerRepository对象的工作委托IRepositorySelector,它只负责IRepositorySelector对象的创建和维护工作。但是IRepositorySelector也只是负责对ILoggerRepository对象的创建和维护工作。所以LoggerManager通过IRepositorySelector获取ILoggerRepository对象,然后再通过获取到的ILoggerRepository对象获取ILogger对象。LoggerManager通过两种方式创建IRepositorySelector对象:从配置文件种获取对象类型或者创建默认对象:DefaultRepositorySelector。另外在LoggerManager中添加了销毁IRepository对象进程监控,即当应用程序进程关闭时,自动销毁IRepository对象,这种监控是在创建LoggerManager的静态构造函数时建立的。

3.6 IRepositorySelector

IRepositorySelector是用来维护ILoggerRepository的,在Log4net框架中,它有两个子类:DefaultRepositorySelector和CompactRepositorySelector。由于CompactRepositorySelector是在嵌入式系统中用到的,所以我们只讨论DefaultRepositorySelector。虽说这是一个默认实现,但也是暂时为止唯一的实现。在此类中,以数据字典的方式维护着对ILoggerRepository的缓存。若是第一次使用某个名字的ILoggerRepository是需要创建的。它有两种创建方式,一是通过程序集属性获取ILoggerRepository的名称和类型,二是通过参数传入ILoggerRepository的名称和类型,然后通过反射创建出对象。另外,若是不通过配置文件配置Log4net设置,而是通过程序集设置,也是通过此类中的方法获取Log4net配置的xml文件,并加载配置。默认情况下使用的是默认的ILoggerRepository名称“log4net-default-repository”,这时是从配置文件“log4net.Config”中取配置项的。

3.7 输出方式IAppender:

IAppender有一个抽象子类:AppenderSkeleton。在此抽象类中完成了IAppender的基本功能的实现,几乎所有的底层类都继承此类。AppenderCollection类是IAppender对象的集合类,方便对IAppender的集合进行维护。

每个ILogger对象需要维护着自己的IAppender集合,并向里面写入日志内容。而这些工作可以看作一个单一的职责,类AppenderAttachedImpl负责此职责。所以IAppender只是拥有AppenderAttachedImpl的一个实例作为成员变量(域)就可以了,然后通过此实例做写入日志工作。

在配置文件中必须有一个<log>节点或<root>节点,用以绑定Appender对象等信息,而若没有<root>节点,ILogger的根节点就无实际意思,而设置的<log>节点为Root的第一层子节点,此时,而其他节点就会作为<log>节点的子节点。这时<log>节点的IAppender就会覆盖Root的IAppender.而其子节点会继承<log>节点的IAppender。

3.8 IFilter

IFilter为输出Logger的过去方案,此过滤方案是负责哪些LoggingEvent应该被处理。过滤方案是在AppenderSkeleton中被使用的,并以以职责链的模式对IFilter对象的维护和使用。

3.9 ILayout

ILayout为消息输出格式的定义类,通过此类,可以格式化输出消息的格式。此类也是在AppenderSkeleton中使用,以格式化输出文字的格式。

3.10 PatternLayout

PatternLayout类中对输出的各种信息以系统框架定义的格式化方式进行格式化。虽说此类中会对ParttenConvertor对象进行缓存,但是还是通过PatternParser创建了一系列PatternConverter对象,并以职责链模式把他们组合在一起。通过这些PatternConvertor对象格式化日志对象内部数据(包括机器名称,用户名,当前进程ID,信息类型等信息)。

3.11 ParttenConverter

对于ParttenConverter系列的类分两个分支:一个是Util/PatternStringConverters下的类,这里的类主要处理系统级别的数据。这些数据需要在加载配置Log4net时加载,PatternString负责对这些对象进行维护,虽说此类中会对ParttenConverter对象进行缓存,但是还是通过PatternParser创建了一系列PatternConverter对象,并以职责链模式把他们组合在一起。而第二个分支是Layout/Pattern目录下的类,这些类用来格式化日志事件LoggerEvent对象内的数据。

3.12 OptionConverter

OptionConverter工具类负责类型转换并解析及获取相应的值。而目标类型存储在ConverterRegistry中,此类负责类型转换器的注册及缓存。OptionConverter从ConverterRegistry中获取相应的目标类。目标类主要是指Util/TypeConverters下的类。其中类PatternLayoutConverter用来转换为PatternLayout对象,PatternStringConverter用来转换为PatternString对象。而类OptionConverter主要在类XmlHierarchyConfigurator中解析配置文件时被调用。

3.13 IObjectRenderer

IObjectRenderer对象及其子类用来以字符串的形式输出对象,在框架中它只有一个子类:DefaultRender,而RenderMap对象时以IObjectRenderer类型为键的映射集合。在ILoggerRepository中被调用,而IObjectRenderer对象则是在XmlHierarchyConfigurator中通过反射被创建,并保存在ILoggerRepository对象中。

3.14 IPlugin

IPlugin对象是用来定义附加的操作行为,IPluginFactory负责创建IPlugin对象,在架构中特性类PluginAttribute继承IPluginFactory。所以需要通过设置程序集特性来配置IPlugin类型,并且在DefaultRepositorySelector中通过反射创建IPlugin对象并加载到ILoggerRepository对象中。

3.15 TextWriterAdapter

TextWriterAdapter是通过适配器模式对TextWriter类进行了封装,以便于创建适用于特殊用户的TextWriter对象。在框架中主要由两类:ProtectCloseTextWriter用来隐藏其Close()函数,QuietTextWriter屏蔽其内部产生的异常,并把异常记录到框架自己的日志里。

3.16 ContextPropertiesBase

ContextPropertiesBase抽象类是上下文属性类的基类,此系列类是用来存储某一类型上下文的字典类。

这些属性分别有GlobalContext,ThreadContext,LogicalThreadContext来创建,并在LoggingEvent,PropertyPatternConverter被调用来生成各种参数。其中LogicalThreadContextProperties是通过CallContext.GetData("log4net.Util.LogicalThreadContextProperties")取得数据,也就是说它支持通过Remoting在客户端与服务器端传输的数据。ThreadContextProperties是通过System.Threading.Thread.GetData(s_threadLocalSlot)来获取数据,即是存储在当前线程的数据插槽中,使之与其它线程隔绝。GlobalContextProperties是全局性上下文属性,存储在字典集合中,包含进程级数据。

3.17 SecurityContext

SecurityContext类用来提供受保护的数据,比如模拟一个系统用户。这是一个抽象类,在框架中有两个个实现NullSecurityContext和WindowsSecurityContext. NullSecurityContext对象是一个空实现,不做任何操作,它由SecurityContextProvider类负责创建。WindowsSecurityContext是对Windows域用户的模拟。这些上下文对象在部分IAppender中被使用,以保证数据操作的安全性,例如:AdoNetAppender,FileAppender等。

3.18 IErrorHandler

IErrorHandler属于异常处理类,它被委托来处理异常。它在框架中只有一个实现类:OnlyOnceErrorHandler,用来在框架内部日志中记录异常信息。异常处理类在AppenderSkeleton中和QuietTextWriter中被使用。

3.19 Log4net目前支持的输出方式包括:

1AdoNetAppender
将日志记录到数据库中。可以采用SQL和存储过程两种方式。

2AnsiColorTerminalAppender
在ANSI窗口终端写下高亮度的日志事件。

3AspNetTraceAppender
能用asp.net中Trace的方式查看记录的日志。

4BufferingForwardingAppender
在输出到子Appenders之前先缓存日志事件。

5ConsoleAppender
将日志输出到控制台。

6EventLogAppender
将日志写到WindowsEventLog.

7FileAppender
将日志写到文件中。

8LocalSyslogAppender
将日志写到localsyslogservice(仅用于UNIX环境下).

9 MemoryAppender
将日志存到内存缓冲区。

10NetSendAppender
将日志输出到WindowsMessengerservice.这些日志信息将在用户终端的对话框中显示。

11RemoteSyslogAppender
通过UDP网络协议将日志写到Remotesyslogservice。

12RemotingAppender
通过.NETRemoting将日志写到远程接收端。

13RollingFileAppender
将日志以回滚文件的形式写到文件中。

14SmtpAppender
将日志写到邮件中。

15TraceAppender
将日志写到.NETtrace系统。

16UdpAppender
将日志connectionlessUDPdatagrams的形式送到远程宿主或以UdpClient的形式广播。

3.20 日志等级:

日志等级分为:(Unrecoverable errors,Recoverable errors,Information,Debug)不可恢复的错误一定要记录下来,用户不可轻易删除,以便于开发人员分析处理。可恢复的错误,也要记录,并提供处理措施,应有查看及分析工具支持。

消息日志用来记录一些关键操作,可作为用户监控,需要分析工具支持。调试日志,用来供开发人员和维护人员跟踪操作流程以及分析问题,平时需要屏蔽,仅在相关维护人员跟踪问题时再临时开放日志权限。

级别

允许的方法

Boolean属性

优先级别

分类

OFF

Highest

FATAL

void Fatal(...);

bool IsFatalEnabled;

Unrecoverable

RROR

void Error(...);

bool IsErrorEnabled;

Recoverable

WARN

void Warn(...);

bool IsWarnEnabled;

INFO

void Info(...);

bool IsInfoEnabled;

Information

DEBUG

void Debug(...);

bool IsDebugEnabled;

Debug

ALL

Lowest

来自:

http://blog.shinylife.net/blog/article.asp?id=948

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值