log4cxx LOG4CXX_ 宏中的可变长度参数
我在一个大型 C++ 项目中使用 log4cxx,但我真的不喜欢 log4cxx 在记录时如何处理多个变量:
LOG4CXX_DEBUG(logger, "test " << var1 << " and " << var3 " and .....)
我更喜欢使用 printf 之类的可变长度参数:
LOG4CXX_DEBUG(logger, "test %d and %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
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, "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;
}
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.
To compile and test this program (in Ubuntu) use :
g++ -o loggertest loggertest.cpp -llog4cxx
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这些方便的宏是标准的 C 宏。
我看不出其中有什么可以使它们保护您定义的函数免于破坏其自己的静态数据。
这些宏确实使用 C++,因此您应该能够从 log_format 函数返回 std::string ,从而避免该问题。
Those convenience macros are standard C macros.
I can see nothing in there that would make them protect a function you define from clobbering its own static data.
The macros do use C++ so you should be able to return a std::string from your log_format function and thus avoid the problem.
该线程表明 log4cxx 确实是线程安全的。
http://old.nabble.com/thread-safe-log4cxx-td17721835。 html
可能想测试一下以确保......
This thread states that log4cxx is indeed thread safe.
http://old.nabble.com/thread-safe-log4cxx-td17721835.html
May want to test just to make sure though...