当前位置:文档之家› Apache log4cxx在C++多进程多线程下的使用

Apache log4cxx在C++多进程多线程下的使用

Apache log4cxx在C++多进程多线程下的使用1、Apache log4cxx介绍Apache log4cxx是Apache Logging Services三个日志记录项目之一,完全开源组件。

是著名的日志记录组件log4j的c++移植版,用于为C++程序提供日志功能,以便开发者对目标程序进行调试和审计。

当前的最新版本为0.10.0。

2、Apache log4cxx 框架组成Apache Log4cxx有三个关键组件,它们是loggers, appenders和layouts。

执行日志操作Logger是log4cxx的核心类。

looger有层次结构,最顶层为RootLogger;logger是分七个级别,分别是debug、info、warn、error、fatal、all、off,最常用的应该是debug()和info();而warn()、error()、fatal()仅在相应事件发生后才使用。

每个logger可以附加多个Appender。

Appender代表了日志输出的目标,如输出到文件、控制台,数据库等等。

对于每一种appender,都可以通过layout进行格式设置,根据自己需求定制不同日志内容。

使用中用到的类有BasicConfigurator、PropertyConfigurator、DOMConfigurator等,用于对log4cxx进行配置。

其中BasicConfigurator提供了一种简单配置,包括使用ConsoleAppder作为root appender和PatternLayout 作为缺省布局,PropertyConfigurator使用properties文件作为配置方式,DOMConfigurator则使用properties文件作为配置方式,具体配置文档信息请查阅相关资料。

3、多进程多线程使用设计Apache Log4cxx 提供的常用供日志调用方法,logger->info(),logger->debug(),logger->warn(),logger->error(),与上述方法类似的还有相应的宏调用LOG4CXX_DEBUG()、LOG4CXX_INFO()、LOG4CXX_WARN()、LOG4CXX_ERROR()。

每个方法与宏的参数要求是全字符串类型,对于不同的日志信息相应调用不同的日志记录方法,即可得到不同级别、不同类型的日志信息。

配置文件的设置Apache Log4cxx提供static void configure(helpers::Properties& properties)函数,参数中传入配置文件的绝对路径或是相对路径、文件名,日志文件名称 Apache Log4cxx 提供static LoggerPtr getLogger(const std::wstring& name);参数中传入日志文件名,用日志文件名称实例化LoggerPtr对象LoggerPtr logger(Logger::getLogger(trace)),即可用通过logger对象调用相应类型日志方法,宏调用也在实例化日志对象后才能对设置信息有作用大家看到了,方法参数要求是一个字符串类型,不便于C++记录日志,也不习惯于C++程序员使用。

配置文件与日志文件名设备,都用到了静态方法,多线程共用一个日志对象,每个线程一个日志文件,上述静态方法是不能满足这个需求的,多个进程里面不用的线程调用此方法,每个线程一个日志文件,就更不能满足需求,所以我们必须自己设计一种结构来封装Apache Log4cxx提供的方法,满足多进程多线程下,一个线程一个日志文件的需求。

设计一种方便的参数传入模式,使C++程序员能方便使用日志组件提供方法。

我的设计模型如下,用动态库封装日志方法,不同进程、不同线程实例化一个动态库对象,便能解决多进程,多线程生成不同文件问题,用类似sprintf()格式化参数,封装日志方法参数,当然也可以用特定格式来规定日志输出,便能解决方便操作问题,实例化封装类对象,为了不再引入Apache Log4cxx头文件信息,我提供两个额外的创建实例,销毁实例方法,这样一个完美的日志服务组件就做成了,下面我们来实现这个设想。

4、多进程多线程使用实现4.1在microsoft Visual C++ 6.0 IDE 上新建一个Win32 Dynamic-Link Library 工程,命名为Trace,选择A simple Dll project,点击Finish一个简单的动态连接库工程就建好了。

4.2 在StdAfx.h文件中包函调用Apache Log4cxx的头文件#include "logger.h"#include "PropertyConfigurator.h"using namespace std;using namespace log4cxx;相应的头文件,动态连接库,静态连接库,部分参考文档,请到Apache Log4cxx 官方网址/下载,官方网址只提供工程文件,相应的动态连接库,静态连接库,需求自己编译得到,具体的编译方法请查阅相关文档。

4.3在工程Trace中新增加一个基础类,命名为CBase用于实现Apache Log4cxx 的配置信息,格式化日志文件的输出信息等作用。

Base .h:#define LOGNAMELNET 100\class CBase{public:CBase(char * PropertyPath,char * TraceName);~CBase();public://格式化日志三角输出框void f_foursquare_sign(char * arg,char *dst);//格式化日志四角输出框void f_triangle_sign(char * arg,char *dst);public://日志对象LoggerPtr m_log;//日志文件名char f_c_logname[LOGNAMELNET];};Base .cpp:CBase::CBase(char * PropertyPath,char * TraceName){log4cxx::PropertyConfigurator::configure(PropertyPath);//configure filethis->m_log = Logger::getLogger(TraceName); //appender//保存日志名称memset(this->f_c_logname,0,sizeof(this->f_c_logname));strcpy(this->f_c_logname,TraceName);}CBase::~CBase(){}void CBase::f_triangle_sign(char * arg,char *dst){char c_str[100*2];memset(c_str,0,sizeof(c_str));strcat(c_str,"<");strcat(c_str,arg);strcat(c_str,">-");strcat(dst,c_str);}void CBase::f_foursquare_sign(char * arg,char *dst){char c_str[100*2];memset(c_str,0,sizeof(c_str));strcat(c_str,"[");strcat(c_str,arg);strcat(c_str,"]-");strcat(dst,c_str);}4.4 增加一个接口类CTraceImpl,向调用者提供接口,这个类只声明接口虚函数,可以直接在项目头文件中实现,额外的创建对象,销毁对象方法也在此声明,实现直接放在项目文件中。

Trace.h:#ifndef __TRACEIMPL__#define __TRACEIMPL__//动态库输出调用约定#define TRACEFUN __declspec(dllexport)class TRACEFUN CTraceImpl{public://重设日志文件名称virtual void ResetTraceName(char * TraceName) = 0;public://输出Debug日志virtual void DebugLog(char * CallName,int LogSign,char * StrMsg,...) = 0;//输出Info日志virtual void InfoLog (char * EventName,int LogSign,char * StrMsg,...) = 0;……};//创建实例TRACEFUN CTraceImpl * CreateTrace(char * PropertyPath = "./log4cxx.properties",char * TraceName = "defilename");//销毁实例TRACEFUN void DestroyTrace(CTraceImpl * pCTrace);#endif // #ifndef __TRACEIMPL__Trace.cpp://创建实例TRACEFUN CTraceImpl * CreateTrace(char * PropertyPath ,char * TraceName ) {//创建新对象return ( new CTrace(PropertyPath,TraceName) );}//销毁实例TRACEFUN void DestroyTrace(CTraceImpl * pCTrace){if (pCTrace){//销毁对象CTraceImpl* fp = (CTraceImpl *)pCTrace;delete fp;}}4.5 新增一个实现类CTrace,从CBase, CTraceImpl继承,实现日志方法的封装,参数的格式化:_Trace.h:class CTrace:public CBase,public CTraceImpl{public://默认配置文件名、日志文件名CTrace(char * PropertyPath ,char * TraceName );~CTrace();public://重设日志文件名称virtual void ResetTraceName(char * TraceName);public://输出Debug日志virtual void DebugLog(char * CallName,int LogSign,char * StrMsg,...);//输出Info日志virtual void InfoLog (char * Name,int LogSign,char * StrMsg,...);……};_Trace.cpp:#define MAXARRAYLEN 1024*2//日志标志#define FUN_BEGIN "BEGIN"#define FUN_END " END "//日志类型#define TYPE_LOG " THREAD "CTrace::CTrace(char * PropertyPath,char * TraceName):CABBase(PropertyPath,TraceName){}CTrace::~CTrace(){void CTrace::InfoLog(char * Name, int LogSign, char *StrMsg, ...) {char c_str[MAXARRAYLEN],c_join_str[MAXARRAYLEN];try{//设置日志文件名称this->m_log = Logger::getLogger(this->f_c_logname);memset(c_join_str,0,sizeof(c_join_str));memset(c_str,0,sizeof(c_str));//日志类型this->f_triangle_sign(TYPE_LOG,c_join_str);//调用方法this->f_foursquare_sign(Name,c_join_str);//日志标志if (LogSign > 0){this->f_triangle_sign(LogSign < 2?FUN_BEGIN:FUN_END,c_join_str);}//格式化参数va_list ap;va_start ( ap, StrMsg );vsprintf(c_str,StrMsg,ap);va_end ( ap );strcat(c_join_str,c_str);//打印日志this->m_log->info(c_join_str);}catch (...){//异常处理strcat(c_join_str,"Format parameter error!!!");this->m_log->info(c_join_str);}}void CTrace::DebugLog(char *CallName, int LogSign, char *StrMsg, ...) {char c_str[MAXARRAYLEN],c_join_str[MAXARRAYLEN];try{//设置日志文件名称this->m_log = Logger::getLogger(this->f_c_logname);memset(c_join_str,0,sizeof(c_join_str));memset(c_str,0,sizeof(c_str));//日志类型this->f_triangle_sign(TYPE_LOG,c_join_str);//调用方法this->f_foursquare_sign(CallName,c_join_str);if (LogSign > 0){this->f_triangle_sign(LogSign < 2?FUN_BEGIN:FUN_END,c_join_str);}//格式化参数va_list ap;va_start ( ap, StrMsg );vsprintf(c_str,StrMsg,ap);va_end ( ap );strcat(c_join_str,c_str);//打印日志this->m_log->debug(c_join_str);}catch (...){//异常处理strcat(c_join_str,"Format parameter error!!!");this->m_log->debug(c_join_str);}}void CTrace::ResetTraceName(char *TraceName){//设置日志名称strcpy(this->f_c_logname,TraceName);}这只实现了Info,debug接口函数,其它方法同理,同一方法也可以以不同的形式实现,对Apache Log4cxx 本实现调用的是成员方法,也可以用宏实现。

相关主题