出处:http://www.cnblogs.com/jyli/archive/2010/02/11/1660606.html
作者:李嘉昱
最近想找个好用的Log工具,比较了一下流行的开源Log工具Log4c,Log4CPP, Log4CXX等,觉得还是Log4c比较合适。
Log4cxx需要依赖于APR。
Log4cpp较log4c移植性稍差些。
Log4c基本上都是一些纯c的东西,移植性比其他二者都要好。
上述工具都很优秀,但用熟练一种工具足以,这样有助于提高效率,以后如果有什么满足不了需要的在考虑其他。
在C项目或是C++项目中都是可以使用log4c,恩,就是它了。
Log4c基本概念
Log4c中有三个重要的概念, Category, Appender, Layout。
Category用于区分不同的Logger, 其实它就是个logger。在一个程序中我们可以通过Category来指定很多的Logger,用于不同的目的。
Appdender用于描述输出流,通过为Category来指定一个Appdender,可以决定将log信息来输出到什么地方去,比如stdout, stderr, 文件, 或者是socket等等
Layout用于指定日志信息的格式,通过为Appender来指定一个Layout,可以决定log信息以何种格式来输出,比如是否有带有时间戳, 是否包含文件位置信息等,以及他们在一条log信息中的输出格式的等。
Log4c使用
log4c使用和其他Log4j系工具一样直截了当。
1
//
初始化
2
log4c_init();
3
//
获取一个已有的category
4
log4c_category_t
*
mycat
=
log4c_category_get(
"
mycat
"
);
5
//
用该category进行日志输出,优先级为DEBUG,输出信息为 "Hello World!"
6
log4c_category_log(mycat, LOG4C_PRIORITY_DEBUG,
"
Hello World!
"
);
Log4c和所有Log4j系的log工具一样,都是可以通过文件配置log特性的。其配置文件采用xml形式,通常叫做log4crc。通过修改log4crc,可以达到配置log4c的目的。
以上代码片段其对应的log4crc可以是
1
<?
xml version="1.0" encoding="ISO-8859-1"
?>
2
<!
DOCTYPE log4c SYSTEM ""
>
3
4
<
log4c
version
="1.2.1"
>
5
<
config
>
6
<
bufsize
>
0
</
bufsize
>
7
<
debug
level
="2"
/>
8
<
nocleanup
>
0
</
nocleanup
>
9
<
reread
>
1
</
reread
>
10
</
config
>
11
....
12
<
category
name
="mycat"
priority
="debug"
appender
="stdout"
/>
13
<
appender
name
="stdout"
type
="stream"
layout
="basic"
/>
14
<
layout
name
="basic"
type
="basic"
/>
15
</
log4c
>
从log4crc中也可以看到Category, Appender, Layout三者之间的关系,一个Category需要为其指定一个appender, 一个appender亦要为其指定一个layout。
Log4c中已经提供了几种默认类型的appender和layout。
appender一般是不需要自己来扩展了,我觉得够用了,一般也就是file, stdout, stderr这几个,而这几种类型Log4c都提供了。
layout我倒是认为有必要扩展一下,Log4c提供的几种默认layout类型信息不够丰富,有时候恐怕无法满足需要。譬如,默认的Layout类型中没有提供能够记录Log事件发生
位置(如文件,行,函数)的格式。所以,如果需要的话就自己定义个格式好了,还是很简单的,我会根据自己的需要和喜好来定义自己的格式。
另外,看这样一条日志记录语句
log4c_category_log(mycat, LOG4C_PRIORITY_DEBUG, "Hello World!");
是不是有点长了呢,每次都敲这么长一串实在是很麻烦,比起log4cpp或者log4cxx相对就简短一些。
首先因为log4c是纯c的东西,就不能以面向对象的方式来调用,在他的log函数中必须指定一个category为参数。
然后才是log level参数, log4c中为log level定义的枚举类型也够长的,像 LOG4C_PRIORITY_DEBUG,LOG4C_PRIORITY_ERROR等,输起来很麻烦。
最后才是你要输出的message.
通过宏的扩展,可以很容易做到让log4c像其他log4j系工具一样使用简单。那就用宏扩展一下吧。
用宏来简化Log4c的使用
看其Log的优先级定义,共有11个。
1
typedef
enum
{
2
/*
* fatal
*/
LOG4C_PRIORITY_FATAL
=
000
,
3
/*
* alert
*/
LOG4C_PRIORITY_ALERT
=
100
,
4
/*
* crit
*/
LOG4C_PRIORITY_CRIT
=
200
,
5
/*
* error
*/
LOG4C_PRIORITY_ERROR
=
300
,
6
/*
* warn
*/
LOG4C_PRIORITY_WARN
=
400
,
7
/*
* notice
*/
LOG4C_PRIORITY_NOTICE
=
500
,
8
/*
* info
*/
LOG4C_PRIORITY_INFO
=
600
,
9
/*
* debug
*/
LOG4C_PRIORITY_DEBUG
=
700
,
10
/*
* trace
*/
LOG4C_PRIORITY_TRACE
=
800
,
11
/*
* notset
*/
LOG4C_PRIORITY_NOTSET
=
900
,
12
/*
* unknown
*/
LOG4C_PRIORITY_UNKNOWN
=
1000
13
} log4c_priority_level_t;
实际上,我觉的用不了那么多优先级,有差不多5个就够了,比如最典型的几个吧,error, warn, info, debug, trace。
1
/*
2
* logger.h
3
*
4
* Created on:
5
* Author: lijy
6
*/
7
8
#ifndef LOGGER_H_
9
#define
LOGGER_H_
10
11
#include
"
log4c.h
"
12
13
#define
LOG_ERROR(category, msg, args...) \
14
{ \
15
const
log4c_location_info_t locinfo
=
LOG4C_LOCATION_INFO_INITIALIZER(NULL);\
16
log4c_category_log_locinfo(mycat,
&
locinfo, LOG4C_PRIORITY_ERROR, msg, ##args); \
17
}
18
19
#define
LOG_WARN(category, msg, args...) \
20
{ \
21
const
log4c_location_info_t locinfo
=
LOG4C_LOCATION_INFO_INITIALIZER(NULL);\
22
log4c_category_log_locinfo(mycat,
&
locinfo, LOG4C_PRIORITY_WARN, msg, ##args); \
23
}
24
25
#define
LOG_INFO(category, msg, args...) \
26
{ \
27
const
log4c_location_info_t locinfo
=
LOG4C_LOCATION_INFO_INITIALIZER(NULL); \
28
log4c_category_log_locinfo(mycat,
&
locinfo, LOG4C_PRIORITY_INFO, msg, ##args); \
29
}
30
31
#define
LOG_DEBUG(category, msg, args...) \
32
{ \
33
const
log4c_location_info_t locinfo
=
LOG4C_LOCATION_INFO_INITIALIZER(NULL); \
34
log4c_category_log_locinfo(mycat,
&
locinfo, LOG4C_PRIORITY_DEBUG, msg, ##args); \
35
}
36
37
#define
LOG_TRACE(category, msg, args...) \
38
{ \
39
const
log4c_location_info_t locinfo
=
LOG4C_LOCATION_INFO_INITIALIZER(NULL);\
40
log4c_category_log_locinfo(mycat,
&
locinfo, LOG4C_PRIORITY_TRACE, msg, ##args); \
41
}
42
43
#endif
/* LOGGER_H_ */
OK,现在同样是输出一个"Hello World!",比较下用宏扩展前后的差别吧
log4c_category_log(mycat, LOG4C_PRIORITY_DEBUG, "Hello World!"); <==>
LOG_DEBUG(mycat, "Hello World!")
应该能少敲不少代码吧。