Аргументы переменной длины в макросах log4cxx LOG4CXX_ - PullRequest
2 голосов
/ 03 июня 2010

Я использую log4cxx в большом проекте C ++, но мне действительно не нравится, как log4cxx обрабатывает несколько переменных при ведении журнала:

LOG4CXX_DEBUG (регистратор, "test" << var1 << "и" << var3 "и .....) </p>

Я предпочитаю использовать 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), используйте:

g++ -o loggertest loggertest.cpp  -llog4cxx

Ответы [ 2 ]

0 голосов
/ 18 сентября 2013

Эти удобные макросы являются стандартными макросами C. Я не вижу там ничего такого, что могло бы защитить их функцию, которую вы определяете, от забивания собственных статических данных.

Макросы действительно используют C ++, поэтому вы должны иметь возможность вернуть std :: string из вашей функции log_format и таким образом избежать проблемы.

0 голосов
/ 03 июня 2010

Этот поток утверждает, что log4cxx действительно безопасен для потоков.

http://old.nabble.com/thread-safe-log4cxx-td17721835.html

Возможно, стоит проверить, чтобы убедиться, что ...

...