log4cpp 是参考 log4j 所写的 c++ 版本的写 log 的库。可以在这里下载
 
 
我的使用方法是:
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

封装log4cp p的更多相关文章

  1. [C#] 简单的 Helper 封装 -- RegularExpressionHelper

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  2. iOS开发之App间账号共享与SDK封装

    上篇博客<iOS逆向工程之KeyChain与Snoop-it>中已经提到了,App间的数据共享可以使用KeyChian来实现.本篇博客就实战一下呢.开门见山,本篇博客会封装一个登录用的SD ...

  3. Ajax实现原理,代码封装

    都知道实现页面的异步操作需要使用Ajax,那么Ajax到是怎么实现异步操作的呢? 首先需要认识一个对象 --> XMLHttpRequest 对象 --> Ajax的核心.它有许多的属性和 ...

  4. 用C语言封装OC对象(耐心阅读,非常重要)

    用C语言封装OC对象(耐心阅读,非常重要) 本文的主要内容来自这里 前言 做iOS开发的朋友,对OC肯定非常了解,那么大家有没有想过OC中NSInteger,NSObject,NSString这些对象 ...

  5. 【知识必备】RxJava+Retrofit二次封装最佳结合体验,打造懒人封装框架~

    一.写在前面 相信各位看官对retrofit和rxjava已经耳熟能详了,最近一直在学习retrofit+rxjava的各种封装姿势,也结合自己的理解,一步一步的做起来. 骚年,如果你还没有掌握ret ...

  6. 对百度WebUploader开源上传控件的二次封装,精简前端代码(两句代码搞定上传)

    前言 首先声明一下,我这个是对WebUploader开源上传控件的二次封装,底层还是WebUploader实现的,只是为了更简洁的使用他而已. 下面先介绍一下WebUploader 简介: WebUp ...

  7. 封装集合(Encapsulate Collection)

    封装就是将相关的方法或者属性抽象成为一个对象. 封装的意义: 对外隐藏内部实现,接口不变,内部实现自由修改. 只返回需要的数据和方法. 提供一种方式防止数据被修改. 更好的代码复用. 当一个类的属性类 ...

  8. CSharpGL(29)初步封装Texture和Framebuffer

    +BIT祝威+悄悄在此留下版了个权的信息说: CSharpGL(29)初步封装Texture和Framebuffer +BIT祝威+悄悄在此留下版了个权的信息说: Texture和Framebuffe ...

  9. CSharpGL(7)对VAO和VBO的封装

    CSharpGL(7)对VAO和VBO的封装 2016-08-13 由于CSharpGL一直在更新,现在这个教程已经不适用最新的代码了.CSharpGL源码中包含10多个独立的Demo,更适合入门参考 ...

随机推荐

  1. 详解java中的TreeSet集合

    TreeSet是实现Set接口的实现类.所以它存储的值是唯一的,同时也可以对存储的值进行排序,排序用的是二叉树原理.所以要理解这个类,必须先简单理解一下什么是二叉树. 二叉树原理简述 假如有这么一个集 ...

  2. HDU-2389

    Rain on your Parade Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 655350/165535 K (Java/Ot ...

  3. 无锁的对象引用:AtomicReference

    http://www.dewen.net.cn/q/9588 首先volatile是java中关键字用于修饰变量,AtomicReference是并发包java.util.concurrent.ato ...

  4. 处理form表单提交后返回值的处理办法【html5】

    同事朋友ajax,最近在弄公司业务电话机,自主搭建,买的设备. 其中最主要功能是前端发起呼叫,通过浏览器触发设备进行呼叫功能,走后台呼叫还不行. 需求是这样的: 前端给设备ip发送特定的一段xml信息 ...

  5. shell日志重定向到null

    用输出重定向符号> 即可,格式如下:shell命令 >/dev/null 若要将标准错误输出也一并重定向,如下:shell命令 >/dev/null 2>&1这样就不管 ...

  6. zoj 4020 The 18th Zhejiang University Programming Contest Sponsored by TuSimple - G Traffic Light(广搜)

    题目链接:The 18th Zhejiang University Programming Contest Sponsored by TuSimple - G Traffic Light 题解: 题意 ...

  7. mongoDB学习第一天之增删改查

    mongoDB 是 no-sql 的一种数据库. 创建数据库: use dbName #数据库中如果存在 dbName ,切换到此数据库:如果不存在此数据库,则创建 dbName 数据库!(tip:当 ...

  8. List 集合中 均匀的取七个点 的值

    场景: 一个未知 长度的 List 集合,可能 长度为7,10,50,100, 等等 这个时候 ,我们需要在 集合中 均匀的取七个点: 思路: n=6; int size = list.Size(); ...

  9. sql查询总结

    1.SQL select 语句 SELECT 语句用于从表中选取数据. 结果被存储在一个结果表中(称为结果集). SELECT 列名称 FROM 表名称 实例: SELECT username,pas ...

  10. 鬼题Ghost [manacher]

    本题目来自five20的周末考试题. Description 给定一个 0/1 序列,求其中满足 " ⺉ " 性质的子串个数. " ⺉ " 性质解释: &quo ...