一、Layout,设置日志输出风格
有BasicLayout、SimpleLayout、PatternLayout,其中BasicLayout,SimpleLayout主要是提供的成型的简单日志风格,实际中基本不会使用,主要是使用PatternLayout对日志做格式输出,Layout是加载到Appender中去的。
涉及头文件:
#include<log4cpp/BasicLayout.hh>
#include<log4cpp/SimpleLayout.hh>
#include<log4cpp/PatternLayout.hh>
BasicLayout: "以时间戳 + 优先级 + 内容"
构造函数:
log4cpp::BasicLayout::BasicLayout()
输出例子格式:
1248337987 ERROR : Hello log4cppin a Error Message!
1248337987 WARN : Hello log4cppin a Warning Message!
SimpleLayout:"优先级 + 日志信息"
log4cpp::SimpleLayout::SimpleLayout()
PatterLayout: "使用类似 printf 的格式化模式"
构造函数:
log4cpp::PatternLayout::PatternLayout()
PatterLayout 设置日志格式函数:
void log4cpp::PatternLayout::setConversionPattern(const std::string &conversionPattern) throw(ConfigureFailure)
使用 PatterLayout 时的格式化参数:
%c category;
%d 日期;日期可以进一步的设置格式,用花括号包围,例如%d{%H:%M:%S,%l} 或者 %d{%d %m
%Y%H:%M:%S,%l}。
%m 消息;
%n 换行符,会根据平台的不同而不同,但对于用户透明;
%p 优先级;
%r 自从 layout 被创建后的毫秒数;
%R 从 1970 年 1 月 1 日 0 时开始到目前为止的秒数;
%u 进程开始到目前为止的时钟周期数;
log4cpp::PatternLayout* pLayout = new log4cpp::PatternLayout();
pLayout->setConversionPattern("%d: [%p] %c %x: %m %n");
appender->setLayout(pLayout);
二、Appender,确定日志输出行为
例如输出到哪儿,如何输出。类Appender是由Category来加载的,一个Category可以加载多个Appender,输出到多个地方,一个Appender也可以被多个Category加载,但是有些Appender类没有设置互斥,日志的多线程支持主要是在Category里做的处理,因此不要使用一个Appender加载到多个Category中。
涉及头文件:
#include <log4cpp/Appender.hh>
#include <log4cpp/OstreamAppender.hh>
#include <log4cpp/StringQueueAppender.hh>
#include <log4cpp/FileAppender.hh>
#include <log4cpp/RollingFileAppender.hh>
OstreamAppender //输出到一个 ostream 类
构造函数:
log4cpp::OstreamAppender::OstreamAppender(const std::string &name, std::ostream stream)
参数:
name the name of the Appender. ===>名称
stream the name of the ostream.===>流名字
举例:
log4cpp::OstreamAppender osAppender = new log4cpp::OstreamAppender("osAppender",&cout);
StringQueueAppender //内存队列
构造函数:
log4cpp::StringQueueAppender::StringQueueAppender(const std::string &name)
举例:
log4cpp::StringQueueAppender* strQAppender =
new log4cpp::StringQueueAppender("strQAppender");
最常用的两个 FileAppender,其功能是将日志写入文件中
FileAppender // 输出到文件
构造函数:
log4cpp::FileAppender::FileAppender (const std::string &name,
const std::string &fileName,
bool append = true,
mode_t mode = 00644)
参数:
name the name of the Appender. ===>名称
fileName the name of the file to which the Appender has to log.===>日志文件名
append whether the Appender has to truncate the file or just append to it if it
already exists. Defaults to 'true'.(===>是否在日志文件后继续记入日志,还是清空原
日志文件再记录)
mode file mode to open the logfile with. Defaults to 00644.
===>文件的打开方式
举例:
log4cpp::FileAppender* fileAppender =
newlog4cpp::FileAppender("fileAppender","wxb.log");
fileAppender->setLayout(pLayout1);
构造函数:
log4cpp::FileAppender::FileAppender (const std::string &name, int fd)
参数:
name the name of the Appender.
fd the file descriptor to which the Appender has to log.
RollingFileAppender
构造函数:
log4cpp::RollingFileAppender::RollingFileAppender(const std::string &name,
const std::string &fileName,
size_t maxFileSize = 10 *1024 *1024,
unsigned int maxBackupIndex = 1,
bool append = true,
mode_t mode = 00644)
参数:
前两个参数与普通文件的类似
第三个参数 maxFileSize:指出了回滚文件的最大值
第四个参数 maxBackupIndex:指出了回滚文件所用的备份文件的最大个数。所谓备份文件,
是用来保存回滚文件中因为空间不足未能记录的日志,备份文件的大小仅比回滚文件的最大
值大 1kb。所以如果 maxBackupIndex 取值为 3,则回滚文件(假设其名称是 rollwxb.log,
大小为 100kb)会有三个备份文件,其名称分别是 rollwxb.log.1,rollwxb.log.2 和
rollwxb.log.3,大小为 101kb。另外要注意:如果 maxBackupIndex 取值为 0 或者小于 0,
则回滚文件功能会失效,其表现如同 FileAppender 一样,不会有大小的限制。这也许是一
个 bug。
第五第六参数同上。
举例:
log4cpp::RollingFileAppender* rollfileAppender =
newlog4cpp::RollingFileAppender( "rollfileAppender","rollwxb.log",5*1024,1);
rollfileAppender->setLayout(pLayout2)
Appender 有个成员函数(方法):
virtual void log4cpp::Appender::setLayout(Layout *layout)
函数用作:设置 appender 格式
参数:layout The layout to use.
三、Category,日志输出主体类
提供了输出各种日志级别的方法,并且能够设置类别优先级,低于此优先级的类都不再输出,可以有多个分类,但每个应用程序都有一个root分类,其他分类都是root分类的子分类,有点类似于java的单继承结构,子分类的输出同时会输出到父分类中。
涉及头文件:
#include<log4cpp/Category.hh>
Log4cpp 中有一个总是可用并实例化好的 Category,即根 Category。
使用log4cpp::Category::getRoot()可以得到根 Category。
在大多数情况下,一个应用程序只需要一个日志种类(Category),但是有时也会用到多个Category,此时可以使用根 Category 的 getInstance 方法来得到子 Category。不同的子Category 用于不同的场合。
构造函数:
log4cpp::Category& root =log4cpp::Category::getRoot();
log4cpp::Category& infoCategory =root.getInstance("infoCategory");
infoCategory.addAppender(osAppender);
infoCategory.setPriority(log4cpp::Priority::INFO);
主要的成员函数:
1、设置 category 的级别
void log4cpp::Category::setPriority (Priority::Value priority) throw
(std::invalid_argument)
Set the priority of this Category.Parameters:
priority The priority to set. Use Priority::NOTSET to let the category use its
parents priority as effective priority.
2、设置或添加 appender
void log4cpp::Category::addAppender (Appender *appender ) throw
(std::invalid_argument) [virtual]
Adds an Appender to this Category.
This method passes ownership from the caller to the Category.
void log4cpp::Category::setAppender (Appender *appender ) [inline]
Adds an Appender to this Category.
This method passes ownership from the caller to the Category.
3、相应日志级别的记录
void log4cpp::Category::warn(const std::string &message) throw ()
Log a message with warn priority.
Parameters:
message string to write in the log file
void log4cpp::Category::warn(const char * stringFormat,... ) throw ()
Log a message with warn priority.
Parameters:
stringFormat Format specifier for the string to write in the log file.
void log4cpp::Category::error(const std::string &message) throw ()
Log a message with error priority.
Parameters:
message string to write in the log file
void log4cpp::Category::error(const char *stringFormat,... ) throw ()
Log a message with error priority.
Parameters:
stringFormat Format specifier for the string to write in the log file.
四、Priority:优先级
用来指定 Category 优先级和日志优先级
涉及头文件:
#include<log4cpp/Priority.hh>
Log4cpp记录日志的原理
每个Category都有一个优先级,该优先级可以由setPriority方法设置,或者从其父 Category 中继承而来。
每条日志也有一个优先级,当 Category 记录该条日志时,若日志优先级高于 Category 的优先级时,该日志被记录,否则被忽略。系统中默认的优先级等级如下:
typedef enum
{
EMERG = 0, // emergency
FATAL = 0, // fatal
ALERT = 100, // alert
CRIT = 200, // critical
ERROR = 300, // error
WARN = 400, // wanning
NOTICE = 500, // notice
INFO = 600, // infomation
DEBUG = 700, // debug
NOTSET = 800
} PriorityLevel;
注意:取值越小,优先级越高。例如一个 Category 的优先级为 101,则所有 EMERG、FATAL、ALERT 日志都可以记录下来,而其他则不能。
Log4cpp 的自动内存管理
Log4cpp 的内存对象管理
Log4cpp 中 new 出来的 Category、Appender 和 Layout 都不需要手动释放,因为 Log4cpp 使
用了一个内部类来管理这些对象。此类的名称是 HierarchyMaintainer,它负责管理 Category 的继承
关系,在程序结束时,HierarchyMaintainer 会依次释放所有 Category,而 Category 则会依次释放拥
有的有效 Appender,Appender 则会释放所有附属的 Layout。如果程序员手动释放这些对象,则会造
成内存报错。从下面的代码可以看出这个特征:
appender->setLayout(new log4cpp::BasicLayout());
这个 new 出来的 BasicLayout 根本就没有保存其指针,所以它只能被 log4cpp 的内存管理类
HierarchyMaintainer 释放。了解到 HierarchyMaintainer 的内存管理方法后,程序员在使用 log4cpp
时应该遵循以下几个使用原则:
- 不要手动释放 Category、Appender 和 Layout;
- 同一个 Appender 不要加入多个 Category,否则它会被释放多次从而导致程序崩溃;
- 同一个 Layout 不要附着到多个 Appender 上,否则也会被释放多次导致程序崩溃;
log4cpp::Category::shutdown()
在不使用 log4cpp 时可调用 log4cpp::Category::shutdown(),其功能如同HierarchyMaintainer 的内存清理。但如果不手动调用,在程序结束时 HierarchyMaintainer 会调用 Category 的析构函数来释放所有 Appender。