2.1.1 Log4cxx主要组成简介
Log4cxx主要是由三部分组成:loggers、appenders和layouts。这三个主要组成部分,协同协作能够使我们根据实际的需要进行日志的输出,它们规定了日志信息的类型和级别、控制应用程序运行时的日志信息组成方式以及日志记录的输出方式。
Logger是Log4cxx的核心,Logger具有继承关系的层次结构,最顶层为RootLogger,每个Logger都有一个级别(Level),每个Logger可以附加多个Appender。Appender代表了日志输出的目标,对于每一个Appender可以通过Layout进行格式配置。
体系结构图:
Logger是什么?Logger就是日志记录器,每一个Logger会对应一组Appenders(输出的目的)以及Level(输出的级别)。
针对于我们的普通的std::out输出来说,日志系统首先也是最主要的优势就是要允许根据开发人员的要求进行日志的选择性输出,如哪些我们不需要输出,哪些又要毫无保留的输出,在什么条件下进行输出、要输出哪些内容以及输出的目标是什么。Log4cxx允许开发人员根据自己选择的开发标准进行日志的分类输出,且可以满足一定条件的输出。
2.1.1 Logger的命名规范
Logger是一个被命名的实体。Logger的命名遵循一个几个规则:
1. Logger的名字是大小写敏感的
2. Logger的名字遵循着继承的概念,具体的描述如下:
一个Logger A我们称它为Logger B的祖先,当Logger B的前缀为“A.”的时候,即A.B。当一个Logger A与它的后代Logger B之间没有其他的Logger时候,我们称Logger A为Logger B的父亲Logger,Logger B为Logger A的儿子Logger。
例如:Logger “com.foo”是Logger “com.foo.Bar”的父亲Logger,com.foo.Bar是com.foo的儿子Logger。这里的命名机制与Java中的继承机制比较类似,它体现的也是Logger本身的继承关系。
当然Log4cxx能够非常简单的进行Logger的命名。我们可以在每一个类中实例化一个Logger,此Logger的名字采用所在类的全名。这是一种很有效和直接的定义Logger的方法,而且可以很容易的帮助我们确认信息的来源(术语哪个类)。当然,这只是一个对Logger命名的建议,事实上也是一般的做法。Log4cxx并没有限制Logger的命名,开发人员可以自由的选择自己想要的Logger名字。
不过还需要强调的一点是:保持Logger与其所在的类的名称一致的方法是目前所知的最好的命名策略。
Logger4cxx官方:
2.1.2 Logger的继承
Logger分为两类:根Logger以及其他的Logger或者成为后代Logger。由于Log4cxx处处体现了继承的思想,本身也是能够灵活的实现继承,所以Logger也是能够被继承的,后代Logger可以继承祖先Logger。但是Root Logger作为根Logger,是没有父亲或是祖先Logger的。
Root Logger位于Logger继承体系的最高点,一切后代Logger都可以继承Root Logger,Root Logger有几下几点区别与其他的Logger:
1. Root Logger作为根Logger,它没有父亲或是祖先Logger
2. Root Logger是一直存在的
3. Root Logger不能通过名字来获取,对于如何获取Root Logger请参阅下一节
一个关于Logger继承的例子(截取自Logger的配置文件当中):
list是list.voice的父亲Logger,list.voice是list的儿子Logger。rootLogger是根Logger。在此例中list和list.voice两个Logger又都继承了rootLogger,不过只是继承了Appenders,Level并没有继承,关于Appenders和Level的继承在稍后的章节将进行介绍。
2.1.3 如何获取Logger
对于Root Logger的获取,我们可以通过调用log4cxx::Logger::getRootLogger静态方法来完成。对于其他的所有Logger可以通过log4cxx::Logger:getLogger方法获取,此方法通过传入想要获取的logger名字作为参数来获取Logger。
下面是Logger class提供的一些基本的成员函数:
从上图中,我们可以看到在命名空间log4cxx下有一个Logger类,该类提供了getRootLogger静态方法来获取根Logger,通过getLogger静态方法获取其他所有的Logger。需要注意的一点是:getLogger方法提供了两个版本以string或wstring作为参数,即支持ANSCII和UNICODE两个版本。
对于后面的宏定义在后面的章节进行介绍,它们是用来记录日志的。
举例说明(1):
举例说明(2):
对于具体Log4cxx的API详细说明请参阅官网:
http://logging.apache.org/log4cxx/apidocs/index.html
当调用getLogger方法的时候,如果我们获取相同名字的Logger,则得到一个引用指向已经存在的相同的Logger对象,如:
Log4cxx的配置环境一般是在应用程序初始化的时候完成的,典型的方式是通过阅读配置文件来完成。这种方式我们会在稍后的章节中进行介绍。
Logger x和y指向相同的Logger对象。因此,基于这个属性,我们可以在配置文件中只配置一个Logger,在程序的不同部分获取这个Logger,而不必通过参数的传递等方法来获取该Logger对象。
Logger的另一个属性是:利用Logger的继承关系,父亲Logger永远可以操作孩子Logger,所以我们可以应用程序或是配置文件中以任意的顺序创建或是配置Logger。尤其是,即使父亲Logger在后代Logger后面创建或是配置,父亲Logger也能够找到并建立于其后代Logger的联系。