log4cplus配置文件、包装类、测试程序示例

本文介绍Log4cplus的日志配置文件设置方法、包装类实现细节,并提供了一个简单的测试程序示例。

开篇提示:本文为本人原创,本文欢迎转载,但必须注明本文出处,例如。
“该文引用自 CruiseYoung的:log4cplus配置文件、包装类、测试程序示例
http://blog.youkuaiyun.com/fksec/article/details/41959005”
否则说明阁下愿意支付以100元人民币每字计的稿费,敬请留意。

1 参考文章

1.1 编译
Visual Studio 2013编译log4cplus: http://blog.youkuaiyun.com/fksec/article/details/38418809
1.2 配置参数
log4cplus配置文件编写及使用: http://blog.youkuaiyun.com/fksec/article/details/41546189

2 配置文件

文件:log4cplus.properties
######################################################
# log4cplus global configuration attributes          #
######################################################
#log4cplus.configDebug=false
#log4cplus.quietMode=false
#log4cplus.disableOverride=false


######################################################
# the root logger configuration                      #
######################################################
#Tokenize=loglevel,Appenders
#INHERITED、OFF, FATAL, ERROR, WARN, INFO, DEBUG, TRACE, ALL, CRITICAL
#log4cplus.rootLogger=TRACE
log4cplus.rootLogger=TRACE,ALogger


######################################################
# non-root loggers configuration                     #
######################################################
#INHERITED
#log4cplus.logger.non_rootLogger=INHERITED
#log4cplus.logger.non_rootLogger=TRACE
#log4cplus.logger.non_rootLogger=TRACE,ALogger
#log4cplus.additivity.non_rootLogger=true


######################################################
# Appender configuration                             #
######################################################
#prefix log4cplus::
#ConsoleAppender、NullAppender、
#FileAppender、RollingFileAppender、DailyRollingFileAppender(File)、TimeBasedRollingFileAppender
#SocketAppender
#NTEventLogAppender、Win32ConsoleAppender、Win32DebugAppender
#SysLogAppender、AsyncAppender(SINGLE_THREADED)
#Log4jUdpAppender
log4cplus.appender.ALogger=log4cplus::DailyRollingFileAppender
#
# Appender common configuration                  #
##################################################
#log4cplus.appender.ALogger.Threshold=ALL
#log4cplus.appender.ALogger.UseLockFile=false
#LockFile的值默认为File的值后加.lock
#log4cplus.appender.ALogger.LockFile=
#log4cplus.appender.ALogger.AsyncAppend=false
#
# ConsoleAppender special configuration          #
##################################################
#log4cplus.appender.ALogger.logToStdErr=false
#log4cplus.appender.ALogger.ImmediateFlush=false
#
# FileAppender common configuration              #
##################################################
log4cplus.appender.ALogger.File=.\log\All.log
#log4cplus.appender.ALogger.ImmediateFlush=true
log4cplus.appender.ALogger.CreateDirs=true
log4cplus.appender.ALogger.Append=true
#log4cplus.appender.ALogger.ReopenDelay=1
#log4cplus.appender.ALogger.BufferSize=0
#GLOBAL DEFAULT USER CLASSIC
#log4cplus.appender.ALogger.Locale=DEFAULT
#
# RollingFileAppender special configuration      #
##################################################
# MB KB 200K(min) 10MB(def)
#log4cplus.appender.ALogger.MaxFileSize=10MB
#log4cplus.appender.ALogger.MaxBackupIndex=1
#
# DailyRollingFileAppender special configuration #
##################################################
# MONTHLY、WEEKLY、DAILY、TWICE_DAILY、HOURLY、MINUTELY
log4cplus.appender.ALogger.Schedule=DAILY
log4cplus.appender.ALogger.MaxBackupIndex=10
#
# TimeBasedRollingFileAppender special configuration #
##################################################
#log4cplus.appender.ALogger.FilenamePattern=%d.log
#log4cplus.appender.ALogger.MaxHistory=10
#log4cplus.appender.ALogger.CleanHistoryOnStart=false
#log4cplus.appender.ALogger.RollOnClose=false
#
# SocketAppender special configuration           #
##################################################
#log4cplus.appender.ALogger.host=
#log4cplus.appender.ALogger.port=9998
#log4cplus.appender.ALogger.ServerName=
#log4cplus.appender.ALogger.IPv6=false
#
# NTEventLogAppender special configuration       #
##################################################
#log4cplus.appender.ALogger.server=
#-10l<=x<<==101
#log4cplus.appender.ALogger.log=Application
#log4cplus.appender.ALogger.source=
#
# Win32ConsoleAppender special configuration     #
##################################################
#log4cplus.appender.ALogger.AllocConsole=true
#log4cplus.appender.ALogger.logToStdErr=false
#log4cplus.appender.ALogger.TextColor=0
#
# SysLogAppender special configuration           #
##################################################
#整数
#log4cplus.appender.ALogger.ident=
#整数
#log4cplus.appender.ALogger.facility=
#log4cplus.appender.ALogger.udp=true
#log4cplus.appender.ALogger.IPv6=false
#log4cplus.appender.ALogger.host=
#log4cplus.appender.ALogger.SyslogHost=
#log4cplus.appender.ALogger.port=514
#
# AsyncAppender special configuration            #
################################################## 
#log4cplus.appender.ALogger.Appender=log4cplus::DailyRollingFileAppender
#log4cplus.appender.ALogger.QueueLimit=2
#
# Log4jUdpAppender special configuration         #
##################################################
#log4cplus.appender.ALogger.host=localhost
#log4cplus.appender.ALogger.port=5000
#log4cplus.appender.ALogger.IPv6=false
#
# CLFSAppender special configuration             #
################################################## 
#log4cplus.appender.ALogger.LogName=
#log4cplus.appender.ALogger.LogSize=512 * 1024
#log4cplus.appender.ALogger.BufferSize=1024 * 64
#
# MSTTSAppender special configuration            #
##################################################
#0<=x<=100
#log4cplus.appender.ALogger.Volume=0
#-10l<=x<<==101
#log4cplus.appender.ALogger.Rate=0
#log4cplus.appender.ALogger.SpeakPunc=false



######################################################
# Layout configuration                               #
######################################################
#prefix log4cplus::
#SimpleLayout、TTCCLayout、PatternLayout
log4cplus.appender.ALogger.layout=log4cplus::TTCCLayout
#
# TTCCLayout special configuration               #
################################################## 
log4cplus.appender.ALogger.layout.DateFormat=ISO8601
log4cplus.appender.ALogger.layout.Use_gmtime=false
log4cplus.appender.ALogger.layout.ThreadPrinting=true
log4cplus.appender.ALogger.layout.CategoryPrefixing=true
log4cplus.appender.ALogger.layout.ContextPrinting=true
#
# PatternLayout special configuration            #
################################################## 
#log4cplus.appender.ALogger.layout.NDCMaxDepth=0
#the "Pattern" property has been deprecated Use "ConversionPattern" instead.
#log4cplus.appender.ALogger.layout.Pattern=
#log4cplus.appender.ALogger.layout.ConversionPattern=%D{%Y/%m/%d %H:%M:%S,%Q} [%t][%r] %-5p - %m [%l:%M]%n


######################################################
# Filter configuration                               #
######################################################
#prefix log4cplus::spi::
#DenyAllFilter、LogLevelMatchFilter、LogLevelRangeFilter、StringMatchFilter
log4cplus.appender.ALogger.filters.1=log4cplus::spi::LogLevelRangeFilter
log4cplus.appender.ALogger.filters.1.AcceptOnMatch=true
log4cplus.appender.ALogger.filters.2=log4cplus::spi::DenyAllFilter
#log4cplus.appender.ALogger.filters.2.AcceptOnMatch=true
# LogLevelMatchFilter special configuration      #
##################################################
#log4cplus.appender.ALogger.filters.1.LogLevelToMatch=TRACE
#
# LogLevelRangeFilter special configuration      #
##################################################
log4cplus.appender.ALogger.filters.1.LogLevelMin=TRACE
log4cplus.appender.ALogger.filters.1.LogLevelMax=FATAL
#
# StringMatchFilter special configuration        #
##################################################
#log4cplus.appender.ALogger.filters.1.StringToMatch=


3 包装类

文件:cruise_log4cplus.hpp
#pragma once


#ifdef CRUISE_LOG4CPLUS

#include <log4cplus/logger.h>
#include <log4cplus/helpers/snprintf.h>
#include <log4cplus/configurator.h>
#include <log4cplus/loggingmacros.h>

class cruise_log4cplus
{
private:
    cruise_log4cplus(){}
    cruise_log4cplus(const cruise_log4cplus& obj)
        : m_logger(obj.m_logger){}
    cruise_log4cplus& operator=(const cruise_log4cplus& obj)
        { m_logger = obj.m_logger; }
    //virtual ~cruise_log4cplus(){}

private:
#define DO_LOGGER(log_level/*, file, line, function, format_msg, __VA_ARGS__*/)    \
    int retval = -1;                                                      \
    try                                                                   \
    {                                                                     \
        if (m_logger.isEnabledFor(log_level))                             \
        {                                                                 \
            const log4cplus::tchar * msg = NULL;                          \
            log4cplus::helpers::snprintf_buf buf;                         \
            std::va_list args;                                            \
            do                                                            \
            {                                                             \
                va_start(args, format_msg);                               \
                retval = buf.print_va_list(msg, format_msg, args);        \
                va_end(args);                                             \
            } while (retval == -1);                                       \
            m_logger.forcedLog(log_level, msg, file, line, function);     \
        }                                                                 \
        retval = 0;                                                       \
    }                                                                     \
    catch (...) {}                                                          

public:
    void Fatal(const char* file, const int line, const char* function,
        const log4cplus::tchar* format_msg, ...)
    {   DO_LOGGER(log4cplus::FATAL_LOG_LEVEL);   }

    void Error(const char* file, const int line, const char* function,
        const log4cplus::tchar* format_msg, ...)
    {   DO_LOGGER(log4cplus::ERROR_LOG_LEVEL);   }

    void Warn(const char* file, const int line, const char* function,
        const log4cplus::tchar* format_msg, ...)
    {   DO_LOGGER(log4cplus::WARN_LOG_LEVEL);   }

    void Info(const char* file, const int line, const char* function,
        const log4cplus::tchar* format_msg, ...)
    {   DO_LOGGER(log4cplus::INFO_LOG_LEVEL);   }

    void Debug(const char* file, const int line, const char* function,
        const log4cplus::tchar* format_msg, ...)
    {   DO_LOGGER(log4cplus::DEBUG_LOG_LEVEL);   }

    void Trace(const char* file, const int line, const char* function,
        const log4cplus::tchar* format_msg, ...)
    {   DO_LOGGER(log4cplus::TRACE_LOG_LEVEL);   }

public:
    void log_init(log4cplus::tchar* prop_file, 
        log4cplus::tchar* prefix_log_flie = NULL,
        log4cplus::tchar* sub_logger_name = NULL)
    {
        log4cplus::initialize();
        m_logger = log4cplus::Logger::getRoot();
		
        if (NULL == prop_file) return;

        try
        {
            if (NULL != prefix_log_flie && '\0' != prefix_log_flie[0])
                change_log_file_name(prop_file, prefix_log_flie);
            else
                log4cplus::PropertyConfigurator::doConfigure(prop_file);
                //log4cplus::ConfigureAndWatchThread cfg_thread(prop_file, 24*60*60*1000);

            if (NULL != sub_logger_name && '\0' != sub_logger_name[0]
                && log4cplus::Logger::exists(sub_logger_name))
                m_logger = log4cplus::Logger::getInstance(sub_logger_name);
            //else
            //    m_logger = log4cplus::Logger::getRoot();

            LOG4CPLUS_INFO(m_logger, LOG4CPLUS_TEXT("Log System Start."));
        }
        catch (...)
        {
            LOG4CPLUS_FATAL(m_logger, LOG4CPLUS_TEXT("Exception occured..."));
			abort();
        }
    }

    void log_uinit()
    {
        LOG4CPLUS_INFO(m_logger, LOG4CPLUS_TEXT("Log System Stop."));

        log4cplus::Logger::shutdown();
    }

private:
    void change_log_file_name(log4cplus::tchar* prop_file,
        log4cplus::tchar* prefix_log_flie)
    {
        log4cplus::PropertyConfigurator prop_config(prop_file);
        log4cplus::helpers::Properties& prop
            = const_cast<log4cplus::helpers::Properties &>(
            prop_config.getProperties());
        log4cplus::helpers::Properties appender_properties
            = prop.getPropertySubset(LOG4CPLUS_TEXT("appender."));
        std::vector<log4cplus::tstring> appenders_props
            = appender_properties.propertyNames();

        for (std::vector<log4cplus::tstring>::iterator
            it = appenders_props.begin(); it != appenders_props.end(); ++it)
        {
            if (log4cplus::tstring::npos != it->find(
                LOG4CPLUS_TEXT(".File")))
            {
                log4cplus::tstring file_name_old
                    = appender_properties.getProperty(*it);
                log4cplus::tstring file_name_new
                    = file_name_add_prefix(file_name_old, prefix_log_flie);

                prop.setProperty(LOG4CPLUS_TEXT("appender.") + *it, file_name_new);
            }
        }

        prop_config.configure();
    }

    log4cplus::tstring file_name_add_prefix(log4cplus::tstring& old_name,
        log4cplus::tstring prefix_flie)
    {
        size_t pos = 0;
        if (log4cplus::tstring::npos != (
            pos = old_name.find_last_of(LOG4CPLUS_TEXT('\\')))
            || log4cplus::tstring::npos != (
            pos = old_name.find_last_of(LOG4CPLUS_TEXT('/'))))
        {
            ++pos;
        }

        prefix_flie.append(LOG4CPLUS_TEXT("_"));
        return old_name.insert(pos, prefix_flie);
    }

public:
    static inline cruise_log4cplus& get_singleton()
    {
        static cruise_log4cplus _instance;
        return _instance;
    }

    static inline cruise_log4cplus* get_singleton_ptr()
    {   return &get_singleton();   }

    static inline log4cplus::Logger& get_logger()
    {   return get_singleton().m_logger;   }

private:
    log4cplus::Logger m_logger;
};

#define g_Log4cplus cruise_log4cplus::get_singleton()
#define g_pLog4cplus cruise_log4cplus::get_singleton_ptr()
#define g_Logger cruise_log4cplus::get_logger()

/************************************************************************/
/*  Log out  macro                                                                                 */
/************************************************************************/
#define LOG_ASSERT(cond)     LOG4CPLUS_ASSERT(g_Logger, cond)
#define LOG_METHOD(logEvent) LOG4CPLUS_TRACE_METHOD(g_Logger, logEvent)

#define LOG_FATAL(logEvent)  LOG4CPLUS_FATAL(g_Logger, logEvent)
#define LOG_ERROR(logEvent)  LOG4CPLUS_ERROR(g_Logger, logEvent)
#define LOG_WARN(logEvent)   LOG4CPLUS_WARN(g_Logger, logEvent)
#define LOG_INFO(logEvent)   LOG4CPLUS_INFO(g_Logger, logEvent)
#define LOG_DEBUG(logEvent)  LOG4CPLUS_DEBUG(g_Logger, logEvent)
#define LOG_TRACE(logEvent)  LOG4CPLUS_TRACE(g_Logger, logEvent)

#if  _MSC_VER > 1400
#define LOG_FATAL_FMT(logFmt, ...) LOG4CPLUS_FATAL_FMT(g_Logger, logFmt, __VA_ARGS__)
#define LOG_ERROR_FMT(logFmt, ...) LOG4CPLUS_ERROR_FMT(g_Logger, logFmt, __VA_ARGS__)
#define LOG_WARN_FMT(logFmt, ...)  LOG4CPLUS_WARN_FMT(g_Logger, logFmt, __VA_ARGS__)
#define LOG_INFO_FMT(logFmt, ...)  LOG4CPLUS_INFO_FMT(g_Logger, logFmt, __VA_ARGS__)
#define LOG_DEBUG_FMT(logFmt, ...) LOG4CPLUS_DEBUG_FMT(g_Logger, logFmt, __VA_ARGS__)
#define LOG_TRACE_FMT(logFmt, ...) LOG4CPLUS_TRACE_FMT(g_Logger, logFmt, __VA_ARGS__)
#endif


/************************************************************************/
/* MACRO: _T, _TEXT, TEXT                                                                     */
/* TYPE: tchar , tstring                                                                            */
/************************************************************************/
#ifndef _T
#define _T(x)   LOG4CPLUS_TEXT(x)
#endif

#ifndef _TEXT
#define _TEXT(x) _T(x)
#endif

#ifndef TEXT
#define TEXT(x) _T(x)
#endif

using log4cplus::tchar;
using log4cplus::tstring;
using log4cplus::tistream;
using log4cplus::tostream;
using log4cplus::tcout;
using log4cplus::tcerr;

#define CRUISE_C_STR_TO_TSTRING(STRING)  LOG4CPLUS_C_STR_TO_TSTRING(STRING)
#define CRUISE_STRING_TO_TSTRING(STRING) LOG4CPLUS_STRING_TO_TSTRING(STRING)
#define CRUISE_TSTRING_TO_STRING(STRING) LOG4CPLUS_TSTRING_TO_STRING(STRING)

#define CRUISE_BUILTIN_EXPECT(exp, c)   LOG4CPLUS_BUILTIN_EXPECT(exp, c)
#define CRUISE_LIKELY(cond)             LOG4CPLUS_LIKELY(cond)
#define CRUISE_UNLIKELY(cond)           LOG4CPLUS_UNLIKELY(cond)

//#define CRUISE_MACRO_FILE()             __FILE__
//#define CRUISE_MACRO_LINE()             __LINE__
#define CRUISE_MACRO_FUNCTION()         LOG4CPLUS_MACRO_FUNCTION()
#define CRUISE_CALLER_FILE()            LOG4CPLUS_CALLER_FILE()
#define CRUISE_CALLER_LINE()            LOG4CPLUS_CALLER_LINE()
#define CRUISE_CALLER_FUNCTION()        LOG4CPLUS_CALLER_FUNCTION()


#else // !CRUISE_LOG4CPLUS

#include <cstdio>   // printf
#include <cstdlib>
#include <iostream> // std::cout, std::cerr, std::endl
#pragma warning(disable:4996)


/************************************************************************/
/* MACRO: _T, _TEXT, TEXT                                                                     */
/* TYPE: tchar , tstring                                                                            */
/************************************************************************/
#ifndef _T
#if UNICODE
#define _T(x)   L ## x
#else
#define _T(x)   x
#endif
#endif

#ifndef _TEXT
#define _TEXT(x) _T(x)
#endif

#ifndef TEXT
#define TEXT(x) _T(x)
#endif

#if UNICODE
typedef wchar_t tchar;
typedef std::wstring tstring;
typedef std::wistream tistream;
typedef std::wostream tostream;
//static tostream& tcout = std::wcout;
//static tostream& tcerr = std::wcerr;
#define tprintf wprintf
#else
typedef char tchar;
typedef std::string tstring;
typedef std::istream tistream;
typedef std::ostream tostream;
//static tostream& tcout = std::cout;
//static tostream& tcerr = std::cerr;
#define tprintf printf
#endif
//typedef std::basic_string<tchar, std::char_traits<tchar>, std::allocator<tchar>> tstring;
//typedef std::basic_ostream<tchar, std::char_traits<tchar> > tostream;
//typedef std::basic_istream<tchar, std::char_traits<tchar> > tistream;

static tostream& get_tcout()
{
#if UNICODE
    static tostream& s_tcout = std::wcout;
#else
    static tostream& s_tcout = std::cout;
#endif
    return s_tcout;
}
#define tcout	get_tcout()

static tostream& get_tcerr()
{
#if UNICODE
    static tostream& s_tcerr = std::wcerr;
#else
    static tostream& s_tcerr = std::cerr;
#endif
    return s_tcerr;
}
#define tcerr	get_tcerr()

static std::string ws2s(const std::wstring& ws)
{
    std::string curLocale = setlocale(LC_ALL, NULL); // curLocale = "C";
    setlocale(LC_ALL, "");
    const wchar_t* _Source = ws.c_str();
    size_t _Dsize = 2 * ws.size() + 1;
    char *_Dest = new char[_Dsize];
    memset(_Dest, 0, _Dsize);
    wcstombs(_Dest, _Source, _Dsize);
    std::string result = _Dest;
    delete[]_Dest;
    setlocale(LC_ALL, curLocale.c_str());
    return result;
}

static std::wstring s2ws(const std::string& s)
{
    setlocale(LC_ALL, "");
    const char* _Source = s.c_str();
    size_t _Dsize = s.size() + 1;
    wchar_t *_Dest = new wchar_t[_Dsize];
    wmemset(_Dest, 0, _Dsize);
    mbstowcs(_Dest, _Source, _Dsize);
    std::wstring result = _Dest;
    delete[]_Dest;
    setlocale(LC_ALL, "C");
    return result;
}

static tstring ws2t(const std::wstring ws)
{
#if UNICODE
    return ws;
#else
    return ws2s(ws);
#endif
}

static tstring s2t(const std::string s)
{
#if UNICODE
    return s2ws(s);
#else
    return s;
#endif
}

static std::string t2s(const tstring s)
{
#if UNICODE
    return ws2s(s);
#else
    return s;
#endif
}

#define CRUISE_C_STR_TO_TSTRING(STRING)  s2t(STRING)
#define CRUISE_STRING_TO_TSTRING(STRING) s2t(STRING)
#define CRUISE_TSTRING_TO_STRING(STRING) t2s(STRING)

/************************************************************************/
/* CRUISE_MACRO_FUNCTION()                                                                */
/* __FILE__, __LINE__                                                                              */
/************************************************************************/
//#define CRUISE_MACRO_FILE()     __FILE__
//#define CRUISE_MACRO_LINE()     __LINE__

#define CRUISE_MACRO_FUNCTION()     0
#if defined(_MSC_VER) && _MSC_VER > 1400
#       undef CRUISE_MACRO_FUNCTION
#       define CRUISE_MACRO_FUNCTION() __FUNCSIG__
#elif defined(__GNUC__)                                         \
    && __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)
#       undef CRUISE_MACRO_FUNCTION
#       define CRUISE_MACRO_FUNCTION() __PRETTY_FUNCTION__
#elif defined(__BORLANDC__) && __BORLANDC__ >= 0x0650
#       undef CRUISE_MACRO_FUNCTION
#       define CRUISE_MACRO_FUNCTION() __FUNCTION__
//#       define CRUISE_MACRO_FUNCTION() __FUNC__ //C++ BuilderX
#elif (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 19901L) \
    || (defined(__GNUC__) && __GNUC__ > 3                       \
        || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
#       undef CRUISE_MACRO_FUNCTION
#       define CRUISE_MACRO_FUNCTION() __func__
#endif

#if defined (__GNUC__)                                          \
    && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))
#   define CRUISE_CALLER_FILE()     __builtin_FILE ()
#   define CRUISE_CALLER_LINE()     __builtin_LINE ()
#   define CRUISE_CALLER_FUNCTION() __builtin_FUNCTION ()
#else
#   define CRUISE_CALLER_FILE()     (NULL)
#   define CRUISE_CALLER_LINE()     (-1)
#   define CRUISE_CALLER_FUNCTION() (NULL)
#endif


class cruise_trace_logger
{
public:
    cruise_trace_logger(const tstring& _msg,
        const char* _file = CRUISE_CALLER_FILE(),
        int _line = CRUISE_CALLER_LINE(),
        char const * _function = CRUISE_CALLER_FUNCTION())
        : msg(_msg), file(_file), function(_function), line(_line)
    {
        tcout << "ENTER: " << msg.c_str()
            << " [" << file << ":" << line << ":" << function << "]"
            << std::endl;
    }

    ~cruise_trace_logger()
    {
        tcout << "EXIT:  " << msg.c_str()
            << " [" << file << ":" << line << ":" << function << "]"
            << std::endl;
    }

private:
    cruise_trace_logger(cruise_trace_logger const &);
    cruise_trace_logger & operator = (cruise_trace_logger const &);

    tstring msg;
    const char* file;
    const char* function;
    int line;
};


/************************************************************************/
/*  Log out  macro                                                                                 */
/************************************************************************/
#define LOG_METHOD(logEvent)                        \
        cruise_trace_logger _trace_logger(logEvent, \
            __FILE__, __LINE__, CRUISE_MACRO_FUNCTION())

#define CRUISE_DEBUG_COUT(logEvent)                 \
    tcout << logEvent << " ["                       \
        << __FILE__ << ":" << __LINE__<< ":"        \
        << CRUISE_MACRO_FUNCTION() << "]" << std::endl
#define CRUISE_DEBUG_CERR(logEvent)                 \
    tcerr << logEvent << " ["                       \
        << __FILE__ << ":" << __LINE__<< ":"        \
        << CRUISE_MACRO_FUNCTION() << "]" << std::endl

#define LOG_FATAL(logEvent)  CRUISE_DEBUG_CERR(logEvent)
#define LOG_ERROR(logEvent)  CRUISE_DEBUG_CERR(logEvent)
#define LOG_WARN(logEvent)   CRUISE_DEBUG_COUT(logEvent)
#define LOG_INFO(logEvent)   CRUISE_DEBUG_COUT(logEvent)
#define LOG_DEBUG(logEvent)  CRUISE_DEBUG_COUT(logEvent)
#define LOG_TRACE(logEvent)  CRUISE_DEBUG_COUT(logEvent)

#if  _MSC_VER > 1400
#define CRUISE_DEBUG_PRINTF(logFmt, ...)                                \
    tprintf(logFmt, __VA_ARGS__);                                       \
    tprintf(_T(" [%s:%d:%s]\n"),                                        \
        CRUISE_C_STR_TO_TSTRING(__FILE__).c_str(), __LINE__,            \
        CRUISE_C_STR_TO_TSTRING(CRUISE_MACRO_FUNCTION()).c_str());

#define LOG_FATAL_FMT(logFmt, ...) CRUISE_DEBUG_PRINTF(logFmt, __VA_ARGS__)
#define LOG_ERROR_FMT(logFmt, ...) CRUISE_DEBUG_PRINTF(logFmt, __VA_ARGS__)
#define LOG_WARN_FMT(logFmt, ...)  CRUISE_DEBUG_PRINTF(logFmt, __VA_ARGS__)
#define LOG_INFO_FMT(logFmt, ...)  CRUISE_DEBUG_PRINTF(logFmt, __VA_ARGS__)
#define LOG_DEBUG_FMT(logFmt, ...) CRUISE_DEBUG_PRINTF(logFmt, __VA_ARGS__)
#define LOG_TRACE_FMT(logFmt, ...) CRUISE_DEBUG_PRINTF(logFmt, __VA_ARGS__)
#endif


#if defined (__GNUC__) && __GNUC__ >= 3
#  define CRUISE_BUILTIN_EXPECT(exp, c) __builtin_expect ((exp), (c))
#else
#  define CRUISE_BUILTIN_EXPECT(exp, c) (exp)
#endif
#define CRUISE_LIKELY(cond) CRUISE_BUILTIN_EXPECT(!! (cond), 1)
#define CRUISE_UNLIKELY(cond) CRUISE_BUILTIN_EXPECT(!! (cond), 0)

#define LOG_ASSERT(cond)                          \
    if (CRUISE_UNLIKELY(!cond))                   \
        LOG_FATAL("failed condition: "#cond);

#endif

static void cruise_set_loc()
{
#if (defined(__linux__) || defined(__linux)        \
    || defined(linux) || defined(__gnu_linux__))   \
        && defined(__GNUC_)
    std::ios::sync_with_stdio(false);	// Linux gcc.
#endif
    std::locale::global(std::locale(""));
#if defined(__MINGW32__)           // Windows32 by mingw compiler 
    setlocale(LC_CTYPE, "");	   // MinGW gcc.
#endif
    tcout.imbue(std::locale(""));
}

static void log_init(tchar* prop_file,
    tchar* prefix_log_flie = NULL, tchar* sub_logger_name = NULL)
{
#ifdef CRUISE_LOG4CPLUS
    g_Log4cplus.log_init(prop_file, prefix_log_flie, sub_logger_name);
#else
    cruise_set_loc();
#endif
}

static void log_uinit()
{
#ifdef CRUISE_LOG4CPLUS
    g_Log4cplus.log_uinit();
#endif
}

4 测试程序

文件:test_log4cplus.cpp
//#define CRUISE_LOG4CPLUS
//#include "cruise_log4cplus_init_single.h"
#include "cruise_log4cplus.hpp"


int main(int argc, char* argv[])
{
    log_init(_T(".\\log4cplus.properties"), _T("aaaa"));
    //for (int i = 0; i < 1000; ++i)
    {

        LOG_METHOD(_TEXT("主函数"));
        LOG_ASSERT(true);
        LOG_ASSERT(false);


        LOG_TRACE(_TEXT("Log4cplus library!") << 2);
        LOG_TRACE_FMT(_TEXT("%d, Log4cplus library!"), 3);
    }

    log_uinit();
    system("pause");
	return 0;
}

log4cplus是C++编写的开源的日志系统,功能非常全面,用到自己开发的工程中会比较专业的,:),本文介绍了log4cplus基本概念,以及如何安装,配置。 ### 简介 ### log4cplus是C++编写的开源的日志系统,前身是java编写的log4j系统.受Apache Software License保护。作者是Tad E. Smith。log4cplus具有线程安全、灵活、以及多粒度控制的特点,通过将信息划分优先级使其可以面向程序调试、运行、测试、和维护等全生命周 期; 你可以选择将信息输出到屏幕、文件、 NT event log、甚至是远程服务器;通过指定策略对日志进行定期备份等等。 ### 下载 ### 最新的log4cplus可以从以下网址下载 http://log4cplus.sourceforge.net本文使用的版本为:1.0.2 ### 安装 ### 1. linux下安装 tar xvzf log4cplus-x.x.x.tar.gz cd log4cplus-x.x.x ./configure --prefix=/where/to/install make make install 这里我采用缺省安装路径:/usr/local,下文如无特别说明,均以此路径为准。 2. windows下安装 不需要安装,有一个msvc6存放包括源代码和用例在内的开发工程(for VC6 only),使用之前请先编译 "log4cplus_dll class"工程生成dll,或者编译"log4cplus_static class"工程生成lib. ### 使用前的配置 ### 1. linux下的配置 确保你的Makefile中包含 /usr/local/lib/liblog4cplus.a(静态库)或 -llog4cplus(动态库)即可, 头文件在/usr/local/include/log4cplus目录下。对于动态库,要想正常使用,还得将库安装路径加入到 LD_LIBRARY_PATH 中,我一般是这样做的:以管理员身份登录,在/etc/ld.so.conf中加入安装路径,这里 是/usr/local/lib,然后执行ldconfig使设置生效即可。 2. windows下的配置 将"log4cplus_dll class"工程或"log4cplus_static class"工程的dsp 文件插入到你的工程中,或者直接 把两个工程编译生成的库以及头文件所在目录放到你的工程的搜索路径中,如果你使用静态库,请在你的工程中 "project/setting/C++"的preprocessor definitions中加入LOG4CPLUS_STATIC。 ### 构成要素介绍 ### 虽然功能强大,应该说log4cplus用起来还是比较复杂的,为了更好地使用它,先介绍一下它的基本要素。 Layouts :布局器,控制输出消息的格式. Appenders :挂接器,与布局器紧密配合,将特定格式的消息输出到所挂接的设备终端 (如屏幕,文件等等)。 Logger :记录器,保存并跟踪对象日志信息变更的实体,当你需要对一个对象进行 记录时,就需要生成一个logger。 Categories :分器,层次化(hierarchy)的结构,用于对被记录信息的分,层次中 每一个节点维护一个logger的所有信息。 Priorities :优先权,包括TRACE, DEBUG, INFO, WARNING, ERROR, FATAL。 本文介绍了log4cplus基本概念,以及如何安装,配置,下一篇将通过例子介绍如何使用log4cplus。 (二) 本文介绍了使用log4cplus有六个步骤,并提供了一些例子引导你了解log4cplus的基本使用。 ### 基本使用 ### 使用log4cplus有六个基本步骤: 1. 实例化一个appender对象 2. 实例化一个layout对象 3. 将layout对象绑定(attach)到appender对象 4. 实例化一个logger对象,调用静态函数:log4cplus::Logger::getInstance("logger_name") 5. 将appender对象绑定(attach)到logger对象,如省略此步骤,标准输出(屏幕)appender对象会绑定到logger 6. 设置logger的优先级,如省略此步骤,各种有限级的消息都将被记录 下面通过一些例子来了解log4cplus的基本使用。 〖例1〗 cpp 代码 /* 严格实现步骤1-6,appender输出到屏幕, 其中的布局格式和LogLevel后面会详细解释。*/ #include #include #include using namespace log4cplus; using namespace log4cplus::helpers; int main(){ /* step 1: Instantiate an appender object */ SharedObjectPtr _append (new ConsoleAppender()); _append->setName("append for test"); /* step 2: Instantiate a layout object */ std::string pattern = "%d{%m/%d/%y %H:%M:%S} - %m [%l]%n"; std::auto_ptr _layout(new PatternLayout(pattern)); /* step 3: Attach the layout object to the appender */ _append->setLayout( _layout ); /* step 4: Instantiate a logger object */ Logger _logger = Logger::getInstance("test"); /* step 5: Attach the appender object to the logger */ _logger.addAppender(_append); /* step 6: Set a priority for the logger */ _logger.setLogLevel(ALL_LOG_LEVEL); /* log activity */ LOG4CPLUS_DEBUG(_logger, "This is the FIRST log message...") sleep(1); LOG4CPLUS_WARN(_logger, "This is the SECOND log message...") return 0; } 输出结果: 10/14/04 09:06:24 - This is the FIRST log message... [main.cpp:31] 10/14/04 09:06:25 - This is the SECOND log message... [main.cpp:33] 〖例2〗 /* 简洁使用模式,appender输出到屏幕。 */ #include #include using namespace log4cplus; using namespace log4cplus::helpers; int main() { /* step 1: Instantiate an appender object */ SharedAppenderPtr _append(new ConsoleAppender()); _append->setName("append test"); /* step 4: Instantiate a logger object */ Logger _logger = Logger::getInstance("test"); /* step 5: Attach the appender object to the logger */ _logger.addAppender(_append); /* log activity */ LOG4CPLUS_DEBUG(_logger, "This is the FIRST log message...") sleep(1); LOG4CPLUS_WARN(_logger, "This is the SECOND log message...") return 0; } 输出结果: DEBUG - This is the FIRST log message... WARN - This is the SECOND log message... 〖例3〗 /* iostream模式,appender输出到屏幕。 */ #include #include #include /* 其实这个东东还是放到log4cplus头文件中比较合适些,个人意见:) */using namespace log4cplus; int main() { /* step 1: Instantiate an appender object */ SharedAppenderPtr _append(new ConsoleAppender()); _append->setName("append test"); /* step 4: Instantiate a logger object */ Logger _logger = Logger::getInstance("test"); /* step 5: Attach the appender object to the logger */ _logger.addAppender(_append); /* log activity */ LOG4CPLUS_TRACE(_logger, "This is" << " just a t" << "est." << std::endl) LOG4CPLUS_DEBUG(_logger, "This is a bool: " << true) LOG4CPLUS_INFO(_logger, "This is a char: " << 'x') LOG4CPLUS_WARN(_logger, "This is a int: " << 1000) LOG4CPLUS_ERROR(_logger, "This is a long(hex): " << std::hex << 100000000) LOG4CPLUS_FATAL(_logger, "This is a double: " << std::setprecision(15) << 1.2345234234) return 0; } 输出结果: DEBUG - This is a bool: 1 INFO - This is a char: x WARN - This is a int: 1000 ERROR - This is a long(hex): 5f5e100 FATAL - This is a double: 1.2345234234 〖例4〗 /* 调试模式,通过loglog来控制输出调试、警告或错误信息,appender输出到屏幕。 */ #include #include using namespace log4cplus::helpers; void printMsgs(void) { std::cout << "Entering printMsgs()..." << std::endl; LogLog::getLogLog()->debug("This is a Debug statement..."); LogLog::getLogLog()->warn("This is a Warning..."); LogLog::getLogLog()->error("This is a Error..."); std::cout << "Exiting printMsgs()..." << std::endl << std::endl; } int main() { /* LogLog实现了debug, warn, error 函数用于输出调试、警告或错误信息, 同时提供了两个方法来进一步控制所输出的信息,其中: setInternalDebugging方法用来控制是否屏蔽输出信息中的调试信息,当输入 参数为false则屏蔽,缺省设置为false。 setQuietMode方法用来控制是否屏蔽所有输出信息,当输入参数为true则屏蔽, 缺省设置为false。 LogLog::getLogLog()->setInternalDebugging(false); */ printMsgs(); std::cout << "Turning on debug..." << std::endl; LogLog::getLogLog()->setInternalDebugging(true); printMsgs(); std::cout << "Turning on quiet mode..." << std::endl; LogLog::getLogLog()->setQuietMode(true); printMsgs(); return 0; } 输出结果: Entering printMsgs()... log4cplus:WARN This is a Warning... log4cplus:ERROR This is a Error... Exiting printMsgs()... Turning on debug... Entering printMsgs()... log4cplus: This is a Debug statement... log4cplus:WARN This is a Warning... log4cplus:ERROR This is a Error... Exiting printMsgs()... Turning on quiet mode... Entering printMsgs()... Exiting printMsgs()... 需要指出的是,输出信息中总是包含"log4cplus:"前缀,有时候会感觉不爽,这是因为LogLog在实现时候死定了要这么写: LogLog::LogLog() : mutex(LOG4CPLUS_MUTEX_CREATE), debugEnabled(false), quietMode(false), PREFIX( LOG4CPLUS_TEXT("log4cplus: ") ), WARN_PREFIX( LOG4CPLUS_TEXT("log4cplus:WARN ") ), ERR_PREFIX( LOG4CPLUS_TEXT("log4cplus:ERROR ") ) { } 你可以把这些前缀换成自己看着爽的提示符号,然后重新编译,hihi。除非万不得已或者实在郁闷的不行,否则还是不要这样干。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值