Variable lenght arguments in log4cxx LOG4CXX_ macros
- by Horacio
I am using log4cxx in a big C++ project but I really don't like how log4cxx handles multiple variables when logging:
LOG4CXX_DEBUG(logger, "test " << var1 << " and " << var3 " and .....)
I prefer using printf like variable length arguments:
LOG4CXX_DEBUG(logger, "test %d and %d", var1, var3)
So I implemented this small wrapper on top of 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, log_format("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);
vsprintf(formatted, 1024, fmt, va);
va_end(va);
return formatted;
}
And this works perfectly but I know using that static variable (formatted) can become problematic if I start using threads and each thread logging to the same place.
I am no expert in log4cxx so I was wondering if the LOG4CXX macros are handling concurrent thread access automatically? or do I have to implement some sort of locking around the log_format method? something that I wan't to avoid due to performance implications.
Also I would like to ask why if I replace the vsprintf inside the log_format method with vsnprintf (that is more secure) then I get nothing printed?
To compile and test this program (in Ubuntu) use :
g++ -o loggertest loggertest.cpp -llog4cxx