オープンソースログシステムlog 4 cplus(六)


この文書は http://www.cppblog.com/tx7do/articles/11720.html
log 4 cplusは多くの面で優れていますが、使用過程には不快なところがあります.自慢し続ける前に、不快な点を少し話してから、スレッドとソケットについての知識を紹介し続けます.####いくつかの改善点###1.ユーザーがLogLevelをカスタマイズする実現メカニズムが不足している.第5編では、ユーザーが自分でLogLevelを定義する方法を紹介したことがある.理想的な効果を実現するために、log 4 cplusのソースコードを変更する必要もある.(2.Loggerオブジェクトを生成するメカニズムは、私が使用している間に、常に異なるファイル、関数で同じloggerを操作する必要があることを改善することができます.log 4 cplusはツリーストレージを実現し、名前に基づいて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コピーが生成され、結果は正しい(ストレージと操作が分離されているため)が、リソースが浪費されているため、log 4 cplusのコードを見てみると、実は以下のように実現できる(概略的):
#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はlog 4 cplusのHierarchyクラスに相当し,同じ名前で同じLoggerインスタンスを取得できることが分かる.
RollingFileAppenderやDailyRollingFileAppenderのパラメータ入力順序が統一されているなど、小さな欠点もありますが、詳しくは言いません.
このセクションでは、log 4 cplusを使用するときに不快な点について説明します.最後のセクションでは、log 4 cplusにおけるスレッドとソケットの実装について説明します.