log4cplus在很多方面做的都很出色,但是使用过程有些地方感觉不爽。在继续吹捧之前我先把不爽之处
稍微提一提,然后继续介绍关于线程和套接字的知识。
### 一些可以改进之处 ###
1. 用户自定义LogLevel的实现机制不够开放
在第五篇中曾经介绍过如何实现用户自行定义LogLevel,为了实现比较理想的效果,甚至还需要改log4cplus
的源代码。:(
2. 生成Logger对象的机制可以改进
我在使用时候,经常需要在不同的文件、函数中操作同一个logger,虽然log4cplus实现了树状存储以及根据
名称生成Logger,却没有充分利用这样的特点确保同一个名称对应的logger对象的唯一性,比如以下代码:
... ...
Logger logger1 = Logger::getInstance("test");
Logger logger2 = Logger::getInstance("test");
Logger * plogger1 = &logger1;
Logger * plogger2 = &logger2;
std::cout << "plogger1: " << plogger1 << std::endl << "plogger2: " << plogger2 << std::endl;
... ...
运行结果:
plogger1: 0xbfffe5a0
plogger2: 0xbfffe580
从结果可以看出,明明是同一个Logger,但每次调用都会产生一个Logger副本,虽然结果是正确的(因为将存
储和操作分开了),但是资源有些浪费,我看了一下log4cplus的代码,其实可以按照如下方式实现(示意性
的):
#include <iostream>
#include <string>
#include <map>
/* forward declaration */
class Logger;
class LoggerContainer
{
public:
~LoggerContainer();
Logger * getinstance(const std::string & strLogger);
private:
typedef std::map<:string,> LoggerMap;
LoggerMap loggerPtrs;
};
class Logger
{
public:
Logger() {std::cout << "ctor of Logger " << std::endl; }
~Logger() {std::cout << "dtor of Logger " << std::endl; }
static Logger * getInstance( const std::string & strLogger)
{
static LoggerContainer defaultLoggerContainer;
return defaultLoggerContainer.getinstance(strLogger);
}
};
LoggerContainer::~LoggerContainer()
{
/* release all ptr in LoggerMap */
LoggerMap::iterator itr = loggerPtrs.begin();
for( ; itr != loggerPtrs.end(); ++itr )
{
delete (*itr).second;
}
}
Logger * LoggerContainer::getinstance(const std::string & strLogger)
{
LoggerMap::iterator itr = loggerPtrs.find(strLogger);
if(itr != loggerPtrs.end())
{
/* logger exist, just return it */
return (*itr).second;
}
else
{
/* return a new logger */
Logger * plogger = new Logger();
loggerPtrs.insert(std::make_pair(strLogger, plogger));
return plogger;
}
}
int main()
{
Logger * plogger1 = Logger::getInstance("test");
Logger * plogger2 = Logger::getInstance("test");
std::cout << "plogger1: " << plogger1 << std::endl << "plogger2: " << plogger2 << std::endl;
return 0;
}
运行结果:
ctor of Logger
plogger1: 0x804fc30
plogger2: 0x804fc30
dtor of Logger
这里的LoggerContainer相当于log4cplus中的Hierarchy类,结果可以看出,通过同一个名称可以获取相同的
Logger实例。
还有一些小毛病比如RollingFileAppender和DailyRollingFileAppender的参数输入顺序可以调整成统一方式
等等,就不细说了。
本部分提到了使用log4cplus时候感觉不爽的地方,最后一部分将介绍一下log4cplus中线程和套接字实现情况。