日志系统

1.日志系统的设计

一般而言,为了设计一个灵活可扩展的可配置的日志库,主要讲日志库分为四个部分设计,分别是:记录器,过滤器,格式化器和输出其四个部分

记录器(日志来源):负责产生日志记录的原始信息,比如(原始信息,日志优先级,时间,记录的位置)等等信息。

过滤器(日志系统优先级):负责按指定的过滤条件过滤掉我们不需要的日志。

格式化器(日志布局):负责对原始日志信息按照我们想要的格式去格式化。

输出器(日志目的地):负责将将要进行记录的日志(一般经过过滤器及格式化器的处理后)记录到日志目的地(例如:输出到文件中)。

2.log4cppc的使用

category 日志记录器
Priority 优先(过滤器)
Layout 布局器
Apperder 输出器(目的地)

简单示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#include "log4cpp/Category.hh"
#include "log4cpp/Appender.hh"
#include "log4cpp/FileAppender.hh"
#include "log4cpp/OstreamAppender.hh"
#include "log4cpp/Layout.hh"
#include "log4cpp/BasicLayout.hh"
#include "log4cpp/Priority.hh"

int main(int argc, char** argv) {
//基类指针指向派生类对象
log4cpp::Appender *appender1 = new log4cpp::OstreamAppender("console", &std::cout);//初始化一个输出器类 前后new的类不一样是因为 OstreamAppender 是Appender 的一个派生类,把前面的类名改为ostreamAppender也是可以的
//OsteramAppender构造函数的第一个参数表示目的地的名字,随便写只是给程序员一个提示,第二个参数是ostream *,例如&cout,对cout取址,意味着输出器会输出到终端
appender1->setLayout(new log4cpp::BasicLayout());
//设置输出器 指针调用setLayout函数,设定布局为BasicLayout

log4cpp::Appender *appender2 = new log4cpp::FileAppender("default", "program.log");
//同样也是生成输出器对象,FileAppender构造函数的参数分别为:第一个同样表示目的地的名字 随便写,第二个表示保存日志的文件名
appender2->setLayout(new log4cpp::BasicLayout());
//输出到文件中的布局也设置为BasicLayout

//下面这几个的调用方法可以看出来是静态函数
//category必须有一个root这样一个根级别的对象
//创建从根节点的category对象,用引用root进行绑定,之后直接在代码中用root指代根节点的category对象
log4cpp::Category& root = log4cpp::Category::getRoot();
root.setPriority(log4cpp::Priority::WARN);
//设置优先级为WARN 代表的是系统的优先级(门槛),作用是用来过滤日志的,例如下面那一堆写入日志的语句要通过这个过滤
//如果日志信息的优先级高于或等于系统的优先级,才会被处理,如果日志的优先级低于系统的优先级会被直接过滤
root.addAppender(appender1);
//指定输出的目的地,这个是输出到终端



//创建叶子级别的category对象 如果什么都不设置,会默认继承父节点的优先级和目的地
//前面的sub1代表是引用的名字,在程序中使用,后面括号里的sub1表示是category的名字代表日志来源
log4cpp::Category& sub1 = log4cpp::Category::getInstance(std::string("sub1"));
/*创建sub1的孩子category对象*/
//log4cpp::Category& sub11 = log4cpp::Category::getInstance(std::string("sub1.sub11"));
//getInstance 单例模式,而且是一个静态的共有的方法
sub1.addAppender(appender2);//写入日志是以追加的形式去写入的
//这是在继承父节点的输出目的地的基础上又追加了输出到文件,所以sub1的效果是即输出到终端又输出到文件
sub1.setAdditivity(false);//不再继承父节点的目的地
sub1.setPriority(Priority:INFO);
//设置自己的sub1优先级

// use of functions for logging messages
root.error("root error");
root.info("root info");
sub1.error("sub1 error");
sub1.warn("sub1 warn");

// printf-style for logging variables
root.warn("%d + %d == %s ?", 1, 1, "two");

// use of streams for logging messages
root << log4cpp::Priority::ERROR << "Streamed root error";
root << log4cpp::Priority::INFO << "Streamed root info";
sub1 << log4cpp::Priority::ERROR << "Streamed sub1 error";
sub1 << log4cpp::Priority::WARN << "Streamed sub1 warn";

// or this way:
root.errorStream() << "Another streamed error";

return 0;
}