ACE使用日志回调机制定制日志格式
ACE日志提供ACE_Log_Msg::MSG_CALLBACK标志,启用此标志后,输出日志的之前会调用我们自己定制的函数,对消息数据可以进行进一步处理。
实现CALLBACK函数,需要写一个日志类,派生自ACE_Log_Msg_Callback类,然后重写里面的log虚函数
class Logger : public ACE_Log_Msg_Callback
{
public:
virtual void log(ACE_Log_Record &log_record);
};
在日志输出之前,会通过调用我们重写的log函数。源码如下:
ssize_t
ACE_Log_Msg::log (ACE_Log_Record &log_record,
int suppress_stderr)
{
// …
if (ACE_BIT_ENABLED (ACE_Log_Msg::flags_,
ACE_Log_Msg::MSG_CALLBACK)
&& this->msg_callback () != 0)
this->msg_callback ()->log (log_record);
// …
}
通过上面知道执行日志回调函数的两个条件:
1. 启用ACE_Log_Msg::MSG_CALLBACK
2. 设置我们Logger对象的指针
调用时会传给我们一个ACE_Log_Record引用的对象,这个对象包含输出日志的信息,因此在log函数内部们就可以对日志定制化。注意在在log函数内部使用ACE_DEBUG等会产生无限递归调用。
示例代码:
#include "ace/Log_Msg.h"
#include "ace/Log_Msg_Callback.h"
#include "ace/Log_Record.h"
#include "ace/OS_NS_stdio.h"
#include "ace/os.h"
class Logger : public ACE_Log_Msg_Callback
{
public:
virtual void log(ACE_Log_Record &log_record);
};
int format_time(const ACE_Time_Value& time_tv, ACE_TCHAR* outbuf, size_t bufsize)
{
if (bufsize == 0)
return 0;
time_t time_tt = time_tv.sec();
struct tm* time_tm = ACE_OS::localtime(&time_tt);
int length = ACE_OS::snprintf(
outbuf, bufsize - 1,
"%04d-%02d-%02d %02d:%02d:%02d.%03d",
time_tm->tm_year+1900, time_tm->tm_mon+1, time_tm->tm_mday,
time_tm->tm_hour, time_tm->tm_min, time_tm->tm_sec,
time_tv.usec()/1000);
return length;
}
void
Logger::log(ACE_Log_Record &log_record)
{
ACE_TCHAR time_str[32];
// 获取时间格式
ACE_Time_Value now = ACE_OS::gettimeofday();
format_time(now, time_str, 32);
// 获取日志等级名称
u_long priority = log_record.priority();
const ACE_TCHAR *priority_name
= log_record.priority_name(ACE_Log_Priority(log_record.type()));
int data_length = log_record.msg_data_len();
data_length += 4; // [] []
data_length += ACE_OS::strlen(time_str); // [time]
data_length += ACE_OS::strlen(priority_name); // [priority name]
ACE_TCHAR* new_format_msg;
ACE_NEW(new_format_msg, ACE_TCHAR[data_length+1]);
const ACE_TCHAR *old_data = log_record.msg_data();
ACE_OS::snprintf(new_format_msg, data_length+1, "[%s][%s]%s",
time_str, priority_name, old_data);
log_record.msg_data(new_format_msg);
}
int ACE_TMAIN(int, ACE_TCHAR *[])
{
ACE_LOG_MSG->set_flags(ACE_Log_Msg::MSG_CALLBACK);
Logger logger;
ACE_LOG_MSG->msg_callback(&logger);
ACE_DEBUG((LM_DEBUG, "(%t) show message!\n"));
return 0;
}