log4cpp总结

来源:互联网 发布:网络技术员培训 编辑:程序博客网 时间:2024/05/04 15:31

一.问题
  1.技术部总是说客户的帐套他们无能为力, 要开发部提供援助,严重的影响了开发进度.
  2.测试员经常发现些偶然出现的问题, 程序员难以重现场景.
二.思路
  1.程序增加往外输出的日志信息;
  2.日志信息要分等级;
  3.外部可以设置某些等级的内容才输出到日志文件;
三.实现
  1.采用Log4cpp库.
  2.需要对Log4cpp进行封装.
    ********************************************************
    /** /file Log4cppWapper.h
   *  /brief 日志输出文件
   */
  
  #ifndef LOG4CPPWAPPER_H
  #define LOG4CPPWAPPER_H
  
  #include <vcl.h>
  #include <classes.hpp>
  #include <string>
  
  #define LogObject static_cast<log4cpp::Category*>(Log4CppWapper::GetInstance().GetCategory())
  
  #define LOG_PRIORITY_FATAL   Log4CppWapper::FATAL
  #define LOG_PRIORITY_ALERT   Log4CppWapper::ALERT
  #define LOG_PRIORITY_CRIT    Log4CppWapper::CRIT
  #define LOG_PRIORITY_ERROR   Log4CppWapper::ERR
  #define LOG_PRIORITY_WARN    Log4CppWapper::WARN
  #define LOG_PRIORITY_NOTICE  Log4CppWapper::NOTICE
  #define LOG_PRIORITY_INFO    Log4CppWapper::INFO
  #define LOG_PRIORITY_DEBUG   Log4CppWapper::DEBUG
  #define LOG_PRIORITY_NOTSET  Log4CppWapper::NOTSET
  
  #define LOGMESSAGE(P, MSG) Log4CppWapper::Log((P), (MSG), __FILE__, __FUNC__, __LINE__);
  #define LOGFILENAME  "sd5000.log"
  
  /**  /brief Log4Cpp外壳 */
  class _export Log4CppWapper
  {
  public:
    /** 优先权等级 */
    typedef enum {
     EMERG  = 0,
        FATAL  = 0,
        ALERT  = 100,
        CRIT   = 200,
        ERR    = 300,
        WARN   = 400,
        NOTICE = 500,
        INFO   = 600,
        DEBUG  = 700,
        NOTSET = 800
        } PriorityLevel;
    /** 取得Log4CppWapper的单件实例 */
    static Log4CppWapper& GetInstance()
    {
      static Log4CppWapper lcw;
      static bool bInited;
      if (!bInited)
      {
        lcw.InitInstance();
        bInited = true;
      }
      return lcw;
    }
    /** 输出日志 */
    static void Log(Log4CppWapper::PriorityLevel priority, const char* szlog);
    /** 输出日志 */
    static void Log(Log4CppWapper::PriorityLevel priority, const std::string& strlog);
    /** 输出日志 */
    static void Log(Log4CppWapper::PriorityLevel priority, const AnsiString& aslog);
    /** 输出日志(包含文件名、函数名及函数) */
    static void Log(Log4CppWapper::PriorityLevel priority, const char* szlog,
      const char* file, const char* func, int line);
    /** 输出日志(包含文件名、函数名及函数) */
    static void Log(Log4CppWapper::PriorityLevel priority, const std::string& strlog,
      const char* file, const char* func, int line);
    /** 输出日志(包含文件名、函数名及函数) */
    static void Log(Log4CppWapper::PriorityLevel priority, const AnsiString& aslog,
      const char* file, const char* func, int line);
    /** 初始化单件实例 */
    void InitInstance();
    /** 取得Log4Cpp输出对象 */
    void* GetCategory(){ return sd_log; }
    ~Log4CppWapper();
  private:
    Log4CppWapper(){};
    /** Log4Cpp输出对象 */
    void* sd_log;
  };
  #endif
  其中, InitInstance()的实现:
  /** 初始化单件实例 */
  void Log4CppWapper::InitInstance()
  {
   // 1. 实例化一个layout 对象
   log4cpp::PatternLayout* layout =
     new log4cpp::PatternLayout();
   layout->setConversionPattern(std::string("%c:%d [%p] %x %m %n"));

   // 2. 初始化一个appender 对象
   log4cpp::Appender* appender = new
         log4cpp::FileAppender("FileAppender",
         AnsiString(ExtractFileDir(Application->ExeName)+"//"+LOGFILENAME).c_str());


   // 3. 把layout对象附着在appender对象上
   appender->setLayout(layout);

   // 4. 实例化一个category对象
   sd_log =
      &log4cpp::Category::getInstance("sdwarn");

   // 5. 设置additivity为false,替换已有的appender
   static_cast<log4cpp::Category*>(sd_log)->setAdditivity(false);

   // 5. 把appender对象附到category上
   static_cast<log4cpp::Category*>(sd_log)->setAppender(appender);

   // 6. 设置category的优先级,低于此优先级的日志不被记录
   PriorityLevel priority = MatchInfo::Instance()->HadOption("SDDEBUG")?
    LOG_PRIORITY_DEBUG:LOG_PRIORITY_WARN;
   static_cast<log4cpp::Category*>(sd_log)->setPriority(priority);
  }
    在这函数的第6步中, 要实现的目标是从外部的文件读出设置, 决定哪些等级的日志需要往外输出.期实现代码如下:
    class MatchInfo
  {
  public:
  /** 验证版本信息函数,通过静态实例调用
  *  /param[in]  被验证的版本信息
   调用格式例如:MatchInfo::Instance()->HadOption("SDDEBUG");
   */
   bool HadOption(AnsiString str){return FOptions.find(UpperCase(str))!=FOptions.end();};
   static MatchInfo* Instance();   ///<静态实例
  private:
   static MatchInfo* _Instance;
   MatchInfo(){};                  ///<构造函数
   std::set<AnsiString> FOptions;  ///<存放版本信息的容器
  };
  //---------------------------------------------------------------------------
  
  
  /***********************************************************************/
  #include "MatchInfo.h"
  //---------------------------------------------------------------------------
  MatchInfo* MatchInfo::_Instance = 0;
  //---------------------------------------------------------------------------
  //静态实例
  MatchInfo* MatchInfo::Instance()
  {
    if (_Instance == 0)
    {
      _Instance = new MatchInfo;
  
      //读文件并将内容放入容器
      if (FileExists("license"))
      {
        TStringList *strList = new TStringList;
        strList->LoadFromFile("license");
        for (int i=0; i<strList->Count; i++)
        {
          _Instance->FOptions.insert(UpperCase(strList->Strings[i]));
        }
        delete strList;
      }
    }
    return _Instance;
  }
  //---------------------------------------------------------------------------

  
  3.调用代码:
    try
    {
      //...
    }
    catch(Exception* E)
    {
      LOGMESSAGE(LOG_PRIORITY_ERROR, E->Message);
      }

原创粉丝点击