关于ACE日志系统的疑问
本帖最后由 wuyudry 于 2010-10-23 15:34 编辑ACE的日志的不如意
ACE的日志部分是一个非常漂亮的实现,在多线程和多进程模型下都能较好的效率和安全使用。但是却又少量的不足,让人意犹未尽。
1无法替换的时间戳格式
ACE日志对于时间戳的格式是固定的,采用的是格式,这个格式在西方人看起来估计还比较顺眼,在东方人眼中却不如人意。更好的方式当然是时间戳的函数可以重载。或者用函数对象(指针)作为参数传入。
虽然这部分代码可以重载解决这个问题,但是要大动干戈只修正这个问题感觉却又不值得的。
2 日志策略的初始化方式别扭
ACE提供了一个日志策略类ACE_Logging_Strategy辅助大家定义日志策略。但是他的初始化参数却是命令行参数,而不是变量参数。
int
ACE_Logging_Strategy::init (int argc, ACE_TCHAR *argv[])
你必须使用这样的命令行去初始化日志策略模块。
-m1024 -N10 -fSTDERR|OSTREAM -s../log/c4ad.log
试问有几个服务器的开发人员会将这些日志策略的初始化放到命令行参数上去。
3 没有按天(时间)分割日志文件的方式
ACE_Logging_Strategy的日志文件的分割策略采用的是按照文件大小分割文件,文件的序号采用滚动的,但这种日志分割方式无法根据文件时间了解日志内容,(由于文件序号要滚动,序号文件的最后修改时间都一样),你只能grep所有的日志寻找你要的内容。
而在我看来,最好日志分割方式肯定是按照日期进行分割日志文件。每天创建一个新的日志文件,可以方便分割日志。清理和管理的工作量大大降低。
4 日志槽的方式
ACE_Logging_Strategy采用的是日志槽的方式Enable或者Disable某些级别的日志。但是感觉多少有点不自然的,ACE自己的日志级别本身就是分级的。个人感觉应该是如果日志输出的日志级别大于定义的级别就能输出应该是一个更好的选择。
解决ACE_Logging_Strategy的问题最好的办法还是扩展这个类。实现自己的日志策略类。
这是网上很早以前的对日志系统的总结了,现在看来似乎还是这个样子。
我现在扩展了ACE_Logging_Strategy,解决了3,4问题。2是就这样了。(不好意思 之前写错了)
不知道1的话,有没有在不修改ACE源码的情况下,解决呢?(这个怎么解决好呢?) 1.看久了也就习惯了,我觉得看着还蛮顺眼的,重载代码是可以解决这个问题,看自己爱好了。
2.,放到启动命令行肯定是比较蠢的办法啦,放到svc.conf中就成了。
3.两个办法
a)改ACE_Logging_Strategy的源代码handle_timeout里面的实现,印象里不是很难得事情。
b)自己搞个定时器,每隔一天(可配置)关闭日志策略,并重新加载一下,也可以满足大部分场景的需求。
4.办法很多,既然你已经解决了,那我就不罗嗦了。 第一点我曾经改过ace内部的一个代码。
其实ace的日志只是能用,他不是专门做日志的。 1.看久了也就习惯了,我觉得看着还蛮顺眼的,重载代码是可以解决这个问题,看自己爱好了。
2.,放到启动命 ...
modern 发表于 2010-10-22 13:08 http://www.acejoy.com/bbs/images/common/back.gif
其实我就是想在不改动源代码的情况下,看有没有办法解决问题1 本帖最后由 modern 于 2010-10-25 14:48 编辑
解决1的办法
改一下代码重编一下而已,不用太纠结。
Log_Msg.cpp:1648
ACE.cpp:2411
替换一下ACE::timestamp就成了。 本帖最后由 wuyudry 于 2010-10-25 10:11 编辑
嗯。是有一点纠结。:lol
1、关于日期分割,我派生了ACE_Logging_Strategy
class ACE_Svc_Export My_Logging_Strategy :public ACE_Logging_Strategy
每次init的时候,检查是否有自己按天数分割保存的参数,然后在检查按大小分割保存注册定时器的地方,判断是否按天数分割保存注册一个在次日00:00:00只触发一次定时器。然后再每次触发定时器的时候,触发次日的。这样OK?
2、关于时间戳呢,现在看着也挺顺眼的了。只是我现在又实现了一个自己的DEBUG宏,总觉得有些不妥的地方。用到了全局静态变量static My_Log_Msg_Callback lmg;
。有什么办法改进?
class ACE_Svc_Export My_Log_Msg_Callback : public ACE_Log_Msg_Callback
{
public:
void log (ACE_Log_Record &log_record)
{
clog << log_record.msg_data () << ACE_TEXT("\n");
ACE_TCHAR pbuf;
ACE_TCHAR date_and_time;
switch(log_record.type ())
{
case LM_DEBUG:
ACE_OS::sprintf(pbuf,
ACE_TEXT("(%d| %s) DEBUG: %s\n"),
ACE_Thread::self (),
ACE::timestamp (log_record.time_stamp (), date_and_time, 35),
log_record.msg_data ());
break;
case LM_INFO:
ACE_OS::sprintf(pbuf,
ACE_TEXT("(%d| %s) INFO : %s\n"),
ACE_Thread::self (),
ACE::timestamp (log_record.time_stamp (), date_and_time, 35),
log_record.msg_data ());
break;
case LM_WARNING:
ACE_OS::sprintf(pbuf,
ACE_TEXT("(%d| %s) WARN : %s\n"),
ACE_Thread::self (),
ACE::timestamp (log_record.time_stamp (), date_and_time, 35),
log_record.msg_data ());
break;
case LM_ERROR:
ACE_OS::sprintf(pbuf,
ACE_TEXT("(%d| %s) ERROR: %s\n"),
ACE_Thread::self (),
ACE::timestamp (log_record.time_stamp (), date_and_time, 35),
log_record.msg_data ());
break;
default:
ACE_OS::sprintf(pbuf,
ACE_TEXT("(%d| %s) UNKNOW: %s\n"),
ACE_Thread::self (),
ACE::timestamp (log_record.time_stamp (), date_and_time, 35),
log_record.msg_data ());
}
log_record.msg_data (pbuf);
}
};
static My_Log_Msg_Callback lmg;
#define MY_DEBUG(X) \
do { \
int const __ace_error = ACE_Log_Msg::last_error_adapter (); \
ACE_Log_Msg *ace___ = ACE_Log_Msg::instance (); \
if(!ACE_LOG_MSG->msg_callback()){\
ACE_LOG_MSG->msg_callback(&lmg);\
ACE_LOG_MSG->set_flags (ACE_Log_Msg::MSG_CALLBACK); ACE_LOG_MSG->clr_flags (ACE_Log_Msg::STDERR || ACE_Log_Msg::LOGGER);}\
ace___->conditional_set (__FILE__, __LINE__, 0, __ace_error); \
ace___->log X; \
} while (0)
ACE的日志系统并不是专门用来做日志记录的,如果你想要更好的日志系统,可以考虑log4cxx、log4cplus,两个都是log4j的C++实现(前者是apache loggging中的一部分,apache logging包括log4j/log4cxx/log4net,后者是另一个开源的实现,在sourceforge上可以找到),ACE可以通过一种简单的方式就可以将消息转发到这两个系统中去,这样,你就可以实现更灵活的日志定制了。
页:
[1]