STDERR 把日志消息输出到标准错误输出流、也就是stderr.
LOGGER 输出到本地的logger守卫程序
OSTREAM 把日志输出到ostream *对象指定的地方。比如可以使用ofstrem指定输出到某个文件。必须调用 msg_ostream成员函数设置一个ostream *对象
MSG_CALLBACK 把日志输出到回调对象。必须自己定义一个从ACE_Log_Msg_Callback继承的子类,并实现新类的log函数和调用ACE_Log_Msg 的msg_callback函数设置一个 ACE_Log_Msg_Callback子类的对象指针。
VERBOSE 在日志消息中记录日志信息的程序名称、线程id、日志记录时间等。默认情况下是不会输出记录日志的时间的,可以通过设置系统环境变量ACE_LOG_TIMESTAMP来输出时间的格式。可以为TIME或者DATE。
VERBOSE_LITE 打印一些是线程相关的信息。
SILENT 不输出任何日志消息、即使设置了STDERR、LOGGER 等输出格式时。
SYSLOG 把日志消息输出到本地系统日志模块。 如 linux的sysylog或者windows的事件 /// Write messages to the user provided backend
CUSTOM 与MAG_CALLBACK类似。必须定义一个从ACE_Log_Msg_Backend继承的子类,并实现新类的log接口。和调用ACE_Log_Msg的msg_backend静态函数设置ACE_Log_Msg_Backend的一个实现的指针。 该标志与MSG_CALLBACK不同的是针对系统当前的所有ACE_Log_Msg都会进行该设置,而MSG_CALLBACK只是设置当前的ACE_Log_Msg对象。
log输出目的地:STDERR 、LOGGER 、OSTREAM 、MSG_CALLBACK 、SYSLOG 、CUSTOM
log输出的附加格式:VERBOSE 、VERBOSE_LITE
set_flags (u_long f) 设置log的输出目的地或格式,可以同时设置多个标志。
clr_flags (u_long f); 取消某个log输出目的地或者格式。
log输出优先级:
enum ACE_Log_Priority
{
LM_SHUTDOWN = 01,
LM_TRACE = 02,
LM_DEBUG = 04,
LM_INFO = 010,
LM_NOTICE = 020,
LM_WARNING = 040,
LM_STARTUP = 0100,
LM_ERROR = 0200,
LM_CRITICAL = 0400,
LM_ALERT = 01000,
LM_EMERGENCY = 02000,
LM_MAX = LM_EMERGENCY,
LM_ENSURE_32_BITS = 0x7FFFFFFF
};
与其说是log输出优先级还不如说他们是log输出的类型。他们在log中都是优先级的标志位来判断是否设定某个输出类型的。
static void disable_debug_messages (ACE_Log_Priority priority = LM_DEBUG); 取消输出某个优先级的日志消息
static void enable_debug_messages (ACE_Log_Priority priority = LM_DEBUG); 使某个优先级的日志消息可以被输出。
让我们的程序使用日志来记录信息。
ACE程序中我们会使用一下几个常用的宏来输出我们的日志消息:
ACE_HEX_DUMP(X) 以16禁止的格式出书X的内容
ACE_RETURN(Y)
ACE_ERROR_BREAK(X)
ACE_ERROR(X)
ACE_DEBUG(X) # 我们最常用的。
ACE_ERROR_INIT(VALUE, FLAGS)
编译时支持日志输出:默认情况下ACE在编译时是支持以上几个宏输出日志消息的。如果不想在自己的程序中输出日志消息时,可以定义宏ACE_NLOGGING ,这样上面所有的宏都会变成一个空的do while语句,不执行任何内容。
运行时支持日志输出:
如果我们不做任何设置的话,那么我们的程序默认是把日志输出到STDERR的。一般的控制台应用程序已经可以满足。
在很多情况下,比如和MFC一起使用时,或者我们想把日志记录到文件时我们就需要重新设置log的输出目的地,通过set_flags/clr_flags设置程序指定的日志输出目的地。
多线程日志输出控制:
ACE_DEBUG等几个预定义的宏所使用的ACE_Log_Msg对象虽然是通过ACE_Log_Msg::instance接口获得的,但是并以意味这整个程序中只有一个ACE_Log_Msg对象。在ACE中如果我们编译的库是属于多线程安全的(一定是多线程安全的,因为我们根本就不会编译,不会基于ACE开发一个单线程的程序)那么对于每一个线程都会有一个ACE_Log_Msg对象。也就是不同的线程在使用ACE_DEBUG输出日志消息时所使用的ACE_Log_Msg对象是不一样的。因此当我们把日志的输出目的或者格式改变而不是使用默认的输出目的地和格式时,我们在每一个线程都需要设置每一个线程所属的ACE_Log_Msg对象的日志消息输出格式。
例外:如果我们的输出目的地是使用CUSTOM 的话,那么我们就不需要设置每一个线程的输出目的地了。因为CUSTOM 的设置是对当前进程的所有线程都生效的。
注意: 如果用户使用CUSTOM 或者MSG_CALLBACK 时,如果在实现的接口log中不加锁时,存在多个线程同时打印输出日志消息的情况。这样就很可能出现2条日志消息在输出的时候交叉在一起。此时我们可以对log函数输出进行加锁。但是加锁的时候,由于log打印或者输出消息到文件或者某些I/O口时,其时间来说相对比较长,这样程序的性能就会比较差劲。
建议:ACE_Log_Msg_Callback或者ACE_Log_Msg_Backend的子类同时继承自ACE_TASK,log接口只实现copy消息,并把消息放入线程专有的消息对了中,由svc接口获取日志信息在打印。也就是在我们的程序中提供一个专门接收日志信息的缓冲队列并输出的线程。