2010-06-03 142 views
2

我使用log4cxx在一個大的C++項目,但我真的不喜歡log4cxx登錄時如何處理多個變量:可變長度參數

LOG4CXX_DEBUG(記錄器,「測試」 < < VAR1 < < 「和」 < < VAR3「和.....)

我更喜歡使用的printf像可變長度參數:

LOG4CXX_DEBUG(記錄器, 」測試%d和%d「,VAR1,VAR3)

所以我實現了這個小包裝上log4cxx

#include <string.h>                                           
#include <stdio.h>                                           
#include <stdarg.h>                                           
#include <log4cxx/logger.h>                                         
#include "log4cxx/basicconfigurator.h"                                      

const char * log_format(const char *fmt, ...);                                    

#define MYLOG_TRACE(logger, fmt, ...) LOG4CXX_TRACE(logger, log_format(fmt, ## __VA_ARGS__))                         
#define MYLOG_DEBUG(logger, fmt, ...) LOG4CXX_DEBUG(logger, log_format(fmt, ## __VA_ARGS__))                         
#define MYLOG_INFO(logger, fmt, ...) LOG4CXX_INFO(logger, log_format(fmt, ## __VA_ARGS__))                         
#define MYLOG_WARN(logger, fmt, ...) LOG4CXX_WARN(logger, log_format(fmt, ## __VA_ARGS__))                         
#define MYLOG_ERROR(logger, fmt, ...) LOG4CXX_ERROR(logger, log_format(fmt, ## __VA_ARGS__))                         
#define MYLOG_FATAL(logger, fmt, ...) LOG4CXX_FATAL(logger, log_format(fmt, ## __VA_ARGS__))                         

static log4cxx::LoggerPtr logger(log4cxx::Logger::getRootLogger());                               

int main(int argc, char **argv)                                        
{                                                
    log4cxx::BasicConfigurator::configure();                                     

    MYLOG_INFO(logger, "Start ");                                        
    MYLOG_WARN(logger, "In running this in %d threads safe?", 1000);                            
    MYLOG_INFO(logger, "End ");                                         

    return 0;                                             
}                                                


const char *log_format(const char *fmt, ...)                                     
{                                                
    va_list va;                                             
    static char formatted[1024];                                        
    va_start(va, fmt);                                           
    vsnprintf(formatted, 1024, fmt, va);                                       
    va_end(va);                                             
    return formatted;                                           
} 

的頂部,這個完美的作品,但我知道使用的是靜態變量(格式化)如果我開始使用線程可以成爲問題,並且每個線程記錄到同一個地方。

我不是log4cxx的專家,所以我想知道如果LOG4CXX宏自動處理併發線程訪問?或者我必須在log_format方法周圍實現某種鎖定?由於性能影響,我不想避免這種情況。

要編譯和測試這個程序(在Ubuntu)使用:即log4cxx確實是線程安全的

g++ -o loggertest loggertest.cpp -llog4cxx 
+0

謝謝。發現這個話題相當有用。我同意使用std :: string的意見,甚至認爲它可能會對性能產生更大的影響。猜測主要的原因是在這種情況下邏輯變得更清潔。 – vitrums 2013-11-25 21:59:56

回答

0

這些方便的宏是標準的C宏。 我可以看到沒有任何東西可以讓他們保護一個你從定義自己的靜態數據中定義的函數。

宏使用C++,所以你應該能夠從你的log_format函數返回一個std :: string,從而避免這個問題。