封装log4cp p

log4cpp 是参考 log4j 所写的 c++ 版本的写 log 的库。可以在这里下载

http://log4cpp.sourceforge.net/

我的使用方法是:

1,定义了一个 _LOG4CPP 宏,用来打开或关闭 log4cpp 的调用,以便在完全不需要 log 的情况下可以运行,例如进行性能测试时;又比如 log4cpp 可能有内存泄露,关闭使用它,可以检查程序其它地方是否有泄露;

2,在写 log 时,自动加上函数名,以方便跟踪运行信息;(在 gcc 可以用可变参数宏定义,vc 中用其它办法,稍后说明)

3,每一个需要写 log 的类,都加上一个静态 log 实例,以方便通过配置,使得相应的 log 可以输出到指定的地方,有利于跟踪特定的运行信息;

4,不直接调用 log4cpp ,而是通过宏定义来使用,原因同1,即有利于关闭 log 功能;

基于以上几点,我写了几个函数及宏定义等,以下逐一说明:

// InitializeLog4cpp 从指定的 log 配置文件中读取信息,并初始化 log4cpp,这个函数在进程的入口处调用

void InitializeLog4cpp(const std::string & logfile);

// ReleaseLog4cpp 用于释入 log4cpp ,在进程的结束处调用

void ReleaseLog4cpp();

// 以下宏用于在类中声明一个静态变量,变量名为 "log"

DECLARE_STATIC_LOG()

// 以下宏用于初如化类中的 log 静态变量

DEFINE_STATIC_LOG(ClassName)

// 以下是用来写 log 信息的几个宏,严重级别分别为 DEBUG, INFO, NOTICE, ERROR

LogDebug

LogInfo

LogNotice

LogError

以下先演示一个应用实例:

Demo.h 文件主要内容:


#include "LogUtils.h"

namespace dk
{


class Demo
{
public:
    Demo();
    virtual ~Demo();
    
public:
    void TestIt(int i, int j);

private:
    DECLARE_STATIC_LOG();

};

}

 

Demo.cpp 文件主要内容:


#include "Demo.h"

namespace dk
{


DEFINE_STATIC_LOG(Demo);

Demo::Demo()
{
    LogInfo("");
}

Demo::~Demo()
{
    LogInfo("");
}

void Demo::TestIt(int i, int j)
{
    LogInfo("i=%d, j=%d", i, j);
}

}

再写个例子来运行,可以看到类似输出

[INFO] - Demo::Demo() - 
[INFO] - Demo::TestIt() - i=1, j=2
[INFO] - Demo::~Demo() -

最后附上完整的

LogUtils.h

LogUtils.cpp

LogTracer.h (这个文件是因为 vc 不支持可变参数的宏,所以采用的取巧方法,这方法是从网上搜来的,出处忘了,请见谅。)

LogUtils.h


#ifndef _LOG_UTILS_H_
#define _LOG_UTILS_H_

#include <string>
#include "LogTracer.h"

#if defined(_LOG4CPP)

#include <log4cpp/Category.hh>

namespace log4cpp
{
    class Category;
};

#endif

namespace dk
{

void InitializeLog4cpp(const std::string & logfile);
void ReleaseLog4cpp();

#if defined (_LOG4CPP)
log4cpp::Category & GetLogCategory(const char * categoryName);
#endif

#if defined (_LOG4CPP)
#    define DECLARE_STATIC_LOG() static log4cpp::Category & log
#    define DEFINE_STATIC_LOG(ClassName) log4cpp::Category & ClassName::log =GetLogCategory(#ClassName)
#else
#    define DECLARE_STATIC_LOG()
#    define DEFINE_STATIC_LOG(ClassName)
#endif

void suck(const char * fmt, ...);

#if defined(_LOG4CPP) && defined(WIN32)
#     define MakePrefix    std::string(__FUNCTION__).append("() - ")
#    define LogDebug     (LogDebuger(log, MakePrefix))
#    define LogInfo        (LogInfoer(log, MakePrefix))
#    define LogNotice     (LogNoticer(log, MakePrefix))
#    define LogError        (LogErrorer(log, MakePrefix))
#elif defined(_LOG4CPP) && !defined(WIN32)
#    defineMakePrefix(fmt)        std::string(__FILE__).append("::").append(__FUNCTION__).append("() - ").append(fmt).c_str()
#    define LogDebug(fmt, ...)    log.debug(MakePrefix(fmt), ##__VA_ARGS__)
#    define LogInfo(fmt, ...)    log.info(MakePrefix(fmt), ##__VA_ARGS__)
#    define LogNotice(fmt, ...)    log.notice(MakePrefix(fmt), ##__VA_ARGS__)
#    define LogError(fmt, ...)    log.error(MakePrefix(fmt), ##__VA_ARGS__)
#else
#    define LogDebug         suck
#    define LogInfo            suck
#    define LogNotice         suck
#    define LogError            suck
#endif

}

#endif

LogUtils.cpp


#include "LogUtils.h"

#if defined(_LOG4CPP)

#include <log4cpp/PropertyConfigurator.hh>

// appenders

#include <log4cpp/Appender.hh>
#include <log4cpp/OstreamAppender.hh>
#include <log4cpp/FileAppender.hh>
#include <log4cpp/RollingFileAppender.hh>
#include <log4cpp/AbortAppender.hh>
#ifdef WIN32
#include <log4cpp/Win32DebugAppender.hh>
#include <log4cpp/NTEventLogAppender.hh>
#endif
#include <log4cpp/RemoteSyslogAppender.hh>
#ifdef LOG4CPP_HAVE_LIBIDSA
#include <log4cpp/IdsaAppender.hh>
#endif    // LOG4CPP_HAVE_LIBIDSA

#ifdef LOG4CPP_HAVE_SYSLOG
#include <log4cpp/SyslogAppender.hh>
#endif

// layouts

#include <log4cpp/Layout.hh>
#include <log4cpp/BasicLayout.hh>
#include <log4cpp/SimpleLayout.hh>
#include <log4cpp/PatternLayout.hh>

#include <log4cpp/Priority.hh>

#endif

namespace dk
{
    
void InitializeLog4cpp(const std::string & logfile)
{
#if defined(_LOG4CPP)
    try
    { 
        log4cpp::PropertyConfigurator::configure(logfile);
    }
    catch (log4cpp::ConfigureFailure & f)
    {
        std::cerr << "Configure Problem " << f.what() << std::endl;
            
//#if defined(WIN32)

//        log4cpp::Appender * appender = new log4cpp::Win32DebugAppender("console");

//#else

log4cpp::Appender * appender = new log4cpp::OstreamAppender("console", &std::cout);
//#endif

log4cpp::PatternLayout * patternLayout = new log4cpp::PatternLayout();
        patternLayout->setConversionPattern("%d [%t] %p - %m%n");

appender->setLayout(patternLayout);
            
        log4cpp::Category & root = log4cpp::Category::getRoot();
        root.addAppender(appender);
        root.setPriority(log4cpp::Priority::DEBUG);
    }
#endif
}

void ReleaseLog4cpp()
{
#if defined(_LOG4CPP)
    log4cpp::Category::shutdown();
#endif
}

#if defined(_LOG4CPP)
log4cpp::Category & GetLogCategory(const char * categoryName)
{
    std::string name = "dk.";
    name.append(categoryName);

return log4cpp::Category::getInstance(name);
}
#endif

void suck(const char * fmt, ...)
{
    if (fmt) {}
}

}

LogTracer.h


#ifndef _LOG_TRACER_H_
#define _LOG_TRACER_H_

#if defined(_LOG4CPP) && defined(WIN32)

#include <log4cpp/Category.hh>

namespace log4cpp
{
    class Category;
};

namespace dk
{

#include <stdarg.h>
#include <stdio.h>

class LogTracer
{
public:
    LogTracer(log4cpp::Category & log, const std::string & prefix)
        : mLog(log)
        , mMsg(prefix)
    {}
  
    void operator()(const char * fmt, ...)
    {
        va_list ap;

va_start(ap, fmt);

AppendString(mMsg, fmt, ap);
        WriteLog(mMsg);

va_end(ap);
    }
    
private:
    virtual void WriteLog(const std::string & message) = 0;

void AppendString(std::string & message, const char * format, va_list args)
    {
        size_t size = 1024;
        char * buffer = new char[size];
     
        while (1)
        {
            int n = _vsnprintf(buffer, size, format, args);
     
            // If that worked, return a string.

if ((n > -1) && (static_cast<size_t>(n) < size))
            {
                message.append(buffer);
                delete [] buffer;
                return;
            }
     
            // Else try again with more space.

size = (n > -1) ?
                n + 1 : // ISO/IEC 9899:1999

size * 2; // twice the old size

delete [] buffer;
            buffer = new char[size];
        }
    }

private:
    // copy-ctor and operator=

LogTracer(const LogTracer &);
    LogTracer & operator=(const LogTracer &);

protected:
    log4cpp::Category & mLog;
    std::string mMsg;
};

class LogDebuger
    : public LogTracer
{
public:
    LogDebuger(log4cpp::Category & log, const std::string & prefix)
        : LogTracer(log, prefix)
    {
    }
    
private:
    virtual void WriteLog(const std::string & message)
    {
        mLog.debug(message);
    }
};

class LogInfoer
    : public LogTracer
{
public:
    LogInfoer(log4cpp::Category & log, const std::string & prefix)
        : LogTracer(log, prefix)
    {
    }
    
private:
    virtual void WriteLog(const std::string & message)
    {
        mLog.info(message);
    }
};

class LogNoticer
    : public LogTracer
{
public:
    LogNoticer(log4cpp::Category & log, const std::string & prefix)
        : LogTracer(log, prefix)
    {
    }
    
private:
    virtual void WriteLog(const std::string & message)
    {
        mLog.notice(message);
    }
};

class LogErrorer
    : public LogTracer
{
public:
    LogErrorer(log4cpp::Category & log, const std::string & prefix)
        : LogTracer(log, prefix)
    {
    }
    
private:
    virtual void WriteLog(const std::string & message)
    {
        mLog.error(message);
    }
};

}

#endif

#endif

时间: 2024-08-28 15:30:22

封装log4cp p的相关文章

python学习 面向对象封装

from collectoins import namedtuplePoint=namedtuple('point',['x','y'])t1=Point(1,2)print(t1.x)print(t1.y)没有方法的类属性不会发生变化    定义简单 不能改变面向对象封装私有属性!!!私有方法!!!用装饰器描述的几个方法@property !!!@classmethod!!@staticmethod! 封装:class Teacher:     def __init__(self,name,p

python—面向对象的封装

封装 私有属性 class Teacher: __identifier = 'Teacher' #私有静态属性 def __init__(self,name,pwd) self.name = name self.__pwd = pwd #私有属性 内部使用,外部不能使用 def pwd(self): print(self.__pwd) alex = Teacher('alex','3714') alex.pwd() class Teacher: __identifier = 'Teacher'

dbutils封装对象,单列,一行一列(用)

基本用法:查找并封装对象与对象集合 public User findUserByNamePassword(String name,String password){ QueryRunner runner = new QueryRunner(DataSourceUtils.getDataSource()); String sql = "select * from user where name='"+name+"' and password = '"+password

python基础--接口与归一化设计、封装、异常、网络编程

1 接口与归一化设计 1.1 归一化概念: 归一化的好处: 1.归一化让使用者无需关心对象的类是什么,只需要知道这些对象都具备某些功能就可以了,这极大降低了使用者的使用难度. 2.归一化使得高层的外部使用者可以不加区分的处理所有接口兼容的对象集合 继承的两种用途 一:继承基类的方法,并且做出自己改变或者扩展(代码重用):实践中,继承的这种用途意义并不很大,甚至常常是有害的.因为它使得子类与基类出现强耦合. 二:声明某个子类兼容于某基类,定义一个接口类(模仿java的Interface),接口类中

自动化测试框架 selenium api的封装

接上一篇 http://tianxietaotao.blog.51cto.com/12002420/1951701 这篇我大概介绍下我这个工具的简单介绍 先上图: 制作背景: Web自动化测试在现在测试领域已经越来越普遍,但是写代码对于好多测试猿代码基础较弱,搭建系统也比较麻烦.所以我抽闲暇时间做了这个简单的工具:下面简单介绍下功能 工具简单介绍: 1.工具栏:Resume:调试阶段执行到下一个断点 next:单步执行 debug/run 模式切换 执行.停止 2.用例树:用例采用execl或者

lambda表达式封装对数据库的查询

前言: 1.为什么要封装lambda表达式数据库查询,原因有一下几点: 1.1.在以往的开发中进行数据库表查询时,其实所需要的字段就是其中几个,但是在开发中,开发者往往习惯select * 进行查询,当数据多和用户量多时,查询的效率会降低. 1.2.在写查询where条件的时候,总是用string.format去拼接字符串,开发效率低. 1.3.代码不够优雅,代码中嵌套和多sql语句,如果是表字段发生改变时编译器检查不出来,代码出错的概率大. 1.4.本着 write less  do more

Android封装TitleBar基本适用所有常规开发

Android封装TitleBar基本适用所有常规开发 github地址:https://github.com/SiberiaDante/SiberiaDanteLib/blob/master/sample/src/main/notes/TitleBar.md 主要实现:(后续会继续完善,喜欢的给个star,感谢支持) 使用方法 allprojects { repositories { ... aven { url 'https://jitpack.io' } } } dependencies

将数据库从服务器移到浏览器--indexedDB基本操作封装

数据库是属于服务器的,这是天经地义的事,但是有时候数据也许并非需要存储在服务器,但是这些数据也是一条一条的记录,怎么办?今天来带领你领略一下H5的一个新特性--indexedDB的风骚.你会情不自禁的发出感叹--不可思议! 一.链接数据库 indexedDB没有创建数据库的概念,你可以直接链接数据库,如果你链接的数据库并不存在,那么会自动的创建一个数据库.看下面的这个例子. <!DOCTYPE html> <html lang="en"> <head>

Java基础——封装

最近学习Java面向对象方面的知识点,一直没时间更新博客,因为这块的知识点真的蛮绕的.一个知识点一个知识点的往外冒,而且对于我这个初学者来说区分构造器和方法就花费了一整天的时间.现在准备再重新过一遍知识点. 先背下来一个理念: 面向对象程序设计是将数据放在第一位的,然后再考虑操作数据的方法. 之前,再学习Java的优越性的时候,我们知道了Java是一种面向对象设计的程序设计语言.那到底什么是面向对象程序设计呢?要弄懂它,首先我们简单了解一下另一种程序设计. 一.面向过程程序设计: 面向过程程序设