现在的位置: 首页 > 综合 > 正文

日志模块(一头文件就实现了日志记录)

2013年08月02日 ⁄ 综合 ⁄ 共 4281字 ⁄ 字号 评论关闭

日志模块(一头文件就实现了日志记录)

温辉敏(wenhm@sina.com)  2009-8-2

摘要:本文介绍了一个C/C++日志记录模块,它是对开源log4c进行的封装和修正的基础上[1][[2][3][4],将所有的代码都集成到一个.h头文件中。带来的革命性突破是日志模块的使用是那么的方便和简单:只要使用一个.h头文件即可无缝的将日志模块嵌入到你的工程中去,不需要再添加额外的的.c/.cpp或是链接lib/dll等,整个日志模块就是一个头文件。日志输出格式方面,提供了C语言传统的字符printf格式输出,同时也为C++提供了ostream方式的流式输出。

关键字: 日志 回滚 日志记录 log4c

日志模块源码和Demohttp://download.csdn.net/source/1568873,或是csdn上搜索上述关键字即可找到。

作者博客:http://blog.csdn.net/wenhm/

 

1.   前言

一直想要找一个使用简单、功能能满足需求、空间占用小能同时能用于CC++语言的日志记录模块,真是梦里寻她千百度,可依旧空山不语无一物。若像《林中路》述说的那样,有两条路供选择到还好,可问题是找不到路,只好在前人的基础上来进行一些封装(Wrapper)以达到目的了。

Log4Cxx/Log4CppC++的库比较大,而且只能用于C++语言,C语言中无法使用。(其实可以使用C 函数来对C++代码进行封装,也可以达到在C语言中使用的目的的,只是自己懒没有去做这方面的工作。)

PWLIBACE等库中也有比较好的日志模块可因为和库关联性太大抽不出来,而且也是只能用于C++语言的。

于是发现log4c这个库还是不错的,C语言写的,整个编下来就几十K,可以支持C语言,至于C++语言只要外层进行下C++ ostream的流式封装就可以使用了。然后加入了PWLIBACE等库的一些比较简单适用的日志记录宏定义以方便适用,比如:

l  基本信息输出:带时间、文件名、行号、线程id、日志级别

l  以十六进制数字方式输出二进制数据块;

l  输出原始数据(不带时间、文件、行号、日志级别)

l  输出函数名;

l  条件日志输出(符合条件才会输出日志)

l  日志输出返回(日志输出后就return)

最后为了追求极限的使用方便,将所有的代码都放在一个头文件中,这样就不用在已有工程中添加日志模块的.c/.cpp,也不用链接日志模块的lib了。就一个头文件的包含就让日志模块无缝的嵌入到你的工程中。

2.   快速上手

2.1. C语言方式日志记录

下面是一个简单的使用日志模块的工程,工程中必须预定义了LOG4C_ENABLE 宏定义才能打开日志(通过该宏定义来控制是否打开日志),工程包含两个.c文件:main.ctest.c。采用Visual Stduio2005编译通过,代码可以去csdn上下载。

 main.c的代码:

--------------------------------------------------------------------------------------------

 #include <stdio.h>

/**下面两条语句将日志模块的实现代码加入进来

#define IMPLEMENT_LOG4C语句一定要在#include "log4c_amalgamation.h"语句之前。

*/

 #define IMPLEMENT_LOG4C

 #include "log4c_amalgamation.h"

 

 extern void test();

 

 void main(int argc, char **argv)

 {

      ///日志模块缺省初始化

      LOG4C_INIT_DEFAULT();

      ///进行日志输出

      LOG4C((LOG_ERROR, "Hello world! My age is %d, and my name is %s!", 28, "Jess" ));

      test();

      ///关闭日志模块防止内存/资源泄漏

      LOG4C_FINI();

 }

--------------------------------------------------------------------------------------------

 

 test.c的代码:

--------------------------------------------------------------------------------------------

 #include <stdio.h>

 #include "log4c_amalgamation.h"

 

 void test()

 {

      ///进行日志输出

      LOG4C((LOG_ERROR, "Hello world! My age is %d, and my name is %s!", 28, "Jess" ));

 }

--------------------------------------------------------------------------------------------

2.2. C++语言方式日志记录

下面是一个简单的使用日志模块的工程,工程中必须预定义了LOG_USELOG4CXX宏定义才能打开日志(通过该宏定义来控制是否打开日志),工程包含两个.cpp文件:main.cpptest.cpp。采用Visual Stduio2005编译通过,代码可以去csdn上下载。

 main.cpp的代码:

--------------------------------------------------------------------------------------------

 #include <stdio.h>

/**下面两条语句将日志模块的实现代码加入进来

#define IMPLEMENT_LOG4C语句一定要在#include "log4c_amalgamation.h"语句之前。

*/

 #define IMPLEMENT_LOG4C

 #include "log4c_amalgamation.h"

 

 extern void test();

 

 void main(int argc, char **argv)

 {

      ///日志模块缺省初始化

      LOG_INIT_DEFAULT();

      ///进行日志输出

      LOG(LOG_LEVEL_FATAL, "test_log_int" <<  "you are the best one!");   

      test();

      ///关闭日志模块防止内存/资源泄漏

      LOG_FINI();

 }

--------------------------------------------------------------------------------------------

 

 test.cpp的代码:

--------------------------------------------------------------------------------------------

 #include <stdio.h>

 #include "log4c_amalgamation.h"

 

 void test()

 {

      ///进行日志输出

      LOG(LOG_LEVEL_ERROR, "Hello world! My age is" << 28 << " and my name is " << "Jess!" );

 }

--------------------------------------------------------------------------------------------

3.   功能介绍

日志输出模块支持Csprintf类型的fromat格式输出,同时也支持C++的流式输出。日志输出的基本内容格式如下:

20090803 11:39:41.656 ThreadID:5552 ERROR - test_usinglog4c.c(27) Hello world!

由上可见,一条日志输出信息中包含了时间(精确到毫秒)、线程ID、日志级别、文件名、行号、用户输出日志信息。

个人觉得时间和线程ID还是非常有用的,特别是线程ID,对于查多线程程序的死锁是非常有帮助的。笔者在中兴时的做的好几个局端项目中服务器程序出现死锁,导致Web HTTP访问无法返回,都是只能立刻使用WatchDog来重启服务器程序,因为不能影响服务。然后拿了打出来的日志分析个天昏地暗,因为有线程ID,总能找到是那几个线程死锁,进而进一步分析问题发生的原因以解决问题。

4.   使用介绍

本日志系统比较简单就一个头文件即可实现日志模块以进行日志的记录,若是就简单的记录日志只要看2.快速上手一节就可以了,下面进行下详细介绍。

4.1. C语言方式使用

4.1.1.    代码中加上日志模块定义

工程中任意一个*.c 文件(记住只要一个c文件有下面的代码就OK,如main函数所在c文件)包含如下代码:

#define IMPLEMENT_LOG4C

#include "log4c_amalgamation.h"

有了上面两行代码就可以将日志模块的代码实现加到你的代码中了,六个字:简单、快捷、方便。这样该.c文件中就可以正常的使用日志模块的所有宏定义来进行日志记录。

4.1.2.    包含日志模块头文件

除了4.1.1中的.c文件外,其它的.c文件都必须包含日志模块头文件,其它要记录日志的*.c 文件包含如下代码:

#include "log4c_amalgamation.h"

这样就可以使用日志模块的所有宏定义来进行日志记录了。

4.1.3.    宏定义开关控制是否打开日志记录

工程中要定义预定义宏定义LOG4C_ENABLE,可以通过控制该宏定义开关来关闭日志模块,若关闭该宏定义则整个工程和没有加入日志模块是一样的,所有的日志宏定义都将失效。

 

4.1.4.    日志模块初始化

日志模块初始化代码,必须调用日志模块初始化代码后才能正确记录日志,只有正确执行了日志模块初始化代码后日志宏定义才能正确进行日志记录。所有在日志模块初始化代码之前执行的日志宏定义都将不能正确记录日志。

日志模块初始化有多个可使用的初始化宏定义,可以按照你程序的特性来选择一个合适的初始化宏定义就好了,下面分别进行介绍。

抱歉!评论已关闭.