ACE
可以将输出重新定向到
stderr
(缺省)、系统日志、输出流(
Output
Stream
)、甚至是回调函数,在
C
/
S
结构中,
ACE
也可以实现客户端输出定向到服务器。本节将详细讨论这些内容。
三 ACE 的重新定向
设置或改变 ACE 日志输出目标( logging sink )可以通过 ACE_Log_Msg 的方法 open 来完成,另外可通过 set_flags 和 clr_flags 来配合实现输出到多个目标。
open 方法的原型: /** * Initialize the ACE logging facility. Supplies the program name * that is available to each logging message call. Default arguments * set up logging to STDERR only. * * @param prog_name The name of the calling program. * @param options_flags A bitwise-or of options flags used to set the * initial behavior and logging sink(s). (see the * enum above for the valid values). * @param logger_key The name of ACE_FIFO rendezvous point where the * local client logger daemon is listening for logging * messages. Only meaningful if the LOGGER bit is * set in the @a flags argument. */ int open ( const ACE_TCHAR * prog_name , u_long options_flags = ACE_Log_Msg :: STDERR , const ACE_TCHAR * logger_key = 0 );
第一个参数 prog_name 表示程序名称,可以任意设置,可通过 ACE_Log_Msg 的 program_name 方法获取,另外当第二个参数设置中有 ACE_Log_Msg :: VERBOSE 时,会在输出信息前加上前缀,前缀中就包含该 program_name 。
第二个参数可以是: STDERR Write messages to STDERRLOGGER Write messages to the local client logger daemonOSTREAM Write messages to the assigned output streamMSG_CALLBACK Write messages to the callback objectVERBOSE Prepends program name , timestamp , host name , process ID , and message priority to each messageVERBOSE_LITE Prepends timestamp and message priority to each messageSILENT Do not print messages at allSYSLOG Write messages to the system 's event logCUSTOM Write messages to the user-provided back end
第三个参数logger key是针对第二个参数为LOGGER(C/S结构)时需要设置的,表示客户端程序端口值,比如:ACE_DEFAULT_LOGGER_KEY。
一旦调用了该方法,其后的输出将重新定位到第二个参数所指定的sink上。
set_flags、clr_flags的原型:
// Enable the bits in the logger' s options flags . void set_flags ( unsigned long f );
// Disable the bits in the logger's options flags.void clr_flags (unsigned long f);
参数含义同 open 函数的第二个参数 options_flags ,其中 set_flags 调用可在现有输出目标基础上增加新的输出目标(叠加), clr_flags 则从中删除指定的输出目标。
下面描述一下重定向到不同 sink 的例子。
1 .输出到 stderr
这个简单: ACE_LOG_MSG -> open ( argv [ 0 ], ACE_Log_Msg :: STDERR ); ACE_DEBUG (( LM_DEBUG , ACE_TEXT ( "test/n" )));
或者: ACE_LOG_MSG -> set_flags ( ACE_Log_Msg :: STDERR ); ACE_DEBUG (( LM_DEBUG , ACE_TEXT ( "test/n" )));
2 .输出到 System Logger
ACE_LOG_MSG -> open ( argv [ 0 ], ACE_Log_Msg :: SYSLOG , ACE_TEXT ( "ACE log" )); ACE_DEBUG (( LM_DEBUG , ACE_TEXT ( "test/n" )));
注意重新定向到 System Logger 不能用 set_flags 、 clr_flags 来实现。 Windows 操作系统下,会输出到系统的 Event Log 中,其中 Event Source 名称为 Open 函数第三个参数。 Unix / Linux 下会输出到 syslog facility 。另外 Windows 下 LM_STARTUP 、 LM_SHUTDOWN 、 LM_TRACE 、 LM_DEBUG 、 LM_INFO 会对应 EVENTLOG_INFORMATION_TYPE ; LM_NOTICE 、 LM_WARNING 会对应 EVENTLOG_WARNING_TYPE 、 LM_ERROR 、 LM_CRITICAL 、 LM_ALERT 、 LM_EMERGENCY 会对应 EVENTLOG_ERROR_TYPE 。
3 .输出到 Output Streams
下例将日志输出到文件( ofstream ):
#include < ace/Log_Msg.h >#include < ace/streams.h >
int ACE_TMAIN ( int , ACE_TCHAR * argv []){ ACE_OSTREAM_TYPE * output = new ofstream ( "test.txt" ); ACE_LOG_MSG -> msg_ostream ( output , 1 ); ACE_LOG_MSG -> set_flags ( ACE_Log_Msg :: OSTREAM ); ACE_LOG_MSG -> clr_flags ( ACE_Log_Msg :: STDERR ); ACE_DEBUG (( LM_DEBUG , ACE_TEXT ( "test/n" )));
return 0 ;}
上例中首先需要通过 msg_ostream 来 assign 一个 ACE OSTREAM ,然后再指定 log sink 为 ACE_Log_Msg :: OSTREAM ,指定 log sink 既可用 set_flags 也可用 open 方法,注意上例中 set_flags 之后紧接着又用 clr_flags 屏蔽掉先前指定的 ACE_Log_Msg :: STDERR (缺省 sink ),这样就不会同时输出到 stderr 了。
看一下 msg_ostream 的注释(解释的很明白,不赘述):
/** * delete_stream == 1, forces Log_Msg.h to delete the stream in * its own ~dtor (assumes control of the stream) * use only with proper ostream (eg: fstream), not (cout, cerr) */ void msg_ostream ( ACE_OSTREAM_TYPE *, int delete_ostream ); 上例中由于设置了 delete_stream == 1 ,所以不应再显示地调用 delete output ;来删除 ofstream 。 全局性的 ostream 还包括 cout 、 cerr 、 clog 等,这里再举一个输出到 cout 的例子,其它情况类似:
ACE_LOG_MSG -> msg_ostream (& cout ); ACE_LOG_MSG -> open ( argv [ 0 ], ACE_Log_Msg :: OSTREAM ); ACE_DEBUG (( LM_DEBUG , ACE_TEXT ( "test/n" )));
4 .输出到 Callback
在 ACE 中,将日志输出重新定向到回调函数其实很简单,只需要四步:
( 1 )定义 ACE_Log_Msg_Callback 的派生类,实现纯虚函数 virtual void log ( ACE_Log_Record & log_record ).
( 2 )在 ACE_Log_Msg 中注册该派生类(比如 MyCallback ): Callback * callback = new Callback ; ACE_LOG_MSG -> set_flags ( ACE_Log_Msg :: MSG_CALLBACK ); ACE_LOG_MSG -> clr_flags ( ACE_Log_Msg :: STDERR ); ACE_LOG_MSG -> msg_callback ( callback ); ( 3 )调用日志输出宏,比如 ACE_DEBUG ,就会将输出重新定向到 MyCallback 的 log 方法中。
( 4 )退出前的清理工作: ACE_LOG_MSG -> clr_flags ( ACE_Log_Msg :: MSG_CALLBACK ); delete callback ;
注意到 ACE_Log_Msg_Callback 的 log 方法的参数类型 ACE_Log_Record , 可以利用其 print 方法重新定制输出:
int print ( const ACE_TCHAR host_name [], u_long verbose_flag , FILE * fp );或者: int print ( const ACE_TCHAR host_name [], u_long verbose_flag , ACE_OSTREAM_TYPE & stream ); 第一个参数表示主机名,第二个参数可选 ACE_Log_Msg :: VERBOSE 、 VERBOSE_LITE 或 0 (原始信息),第三个参数可以是文件指针或者是标准输出流,比如:
log_record . print ( ACE_TEXT ( "" ), ACE_Log_Msg :: VERBOSE , cout ); /* 输出到屏幕 */ log_record . print ( ACE_TEXT ( "" ), 0 , ofstream ( "test.txt" , ios :: app )); /* 输出到文件 */
关于 ACE_Log_Record 进一步使用,请参考以下例子:
/* main.cpp */#include < ace/Task.h >#include < ace/Log_Msg.h >#include " MyCallback.h "
int ACE_TMAIN ( int , ACE_TCHAR *[]){ MyCallback * callback = new MyCallback ;
ACE_LOG_MSG -> set_flags ( ACE_Log_Msg :: MSG_CALLBACK ); ACE_LOG_MSG -> clr_flags ( ACE_Log_Msg :: STDERR ); ACE_LOG_MSG -> msg_callback ( callback );
ACE_DEBUG (( LM_DEBUG , ACE_TEXT ( "test1/n" ))); ACE_DEBUG (( LM_INFO , ACE_TEXT ( "test2/n" )));
ACE_LOG_MSG -> clr_flags ( ACE_Log_Msg :: MSG_CALLBACK ); delete callback ;
return 0 ;}
/* MyCallback.h */#include < ace/streams.h >#include < ace/Log_Msg.h >#include < ace/Log_Msg_Callback.h >#include < ace/Log_Record.h >#include < ace/streams.h >#include < ace/Log_Msg_Callback.h >#include < ace/Log_Record.h >#include < ace/SString.h >#include < ace/OS.h >
class MyCallback : public ACE_Log_Msg_Callback { public : void log ( ACE_Log_Record & log_record ) { cerr << "Log Message Received:" << endl ; unsigned long msg_severity = log_record . type ();
ACE_Log_Priority prio = ACE_static_cast ( ACE_Log_Priority , msg_severity ); const ACE_TCHAR * prio_name = ACE_Log_Record :: priority_name ( prio ); cerr << "/tType: " << ACE_TEXT_ALWAYS_CHAR ( prio_name ) << endl ;
cerr << "/tLength: " << log_record . length () << endl ;
const time_t epoch = log_record . time_stamp (). sec (); cerr << "/tTime_Stamp: " << ACE_TEXT_ALWAYS_CHAR ( ACE_OS :: ctime (& epoch )) << flush ;
cerr << "/tPid: " << log_record . pid () << endl ;
ACE_CString data ( ">> " ); data += ACE_TEXT_ALWAYS_CHAR ( log_record . msg_data ());
cerr << "/tMsgData: " << data . c_str () << endl ; }};
输出: Log Message Received : Type : LM_DEBUG Length : 32 Time_Stamp : Mon Mar 27 17 : 03 : 06 2005 Pid : 2752 MsgData : >> test1
Log Message Received : Type : LM_INFO Length : 32 Time_Stamp : Mon Mar 27 17 : 03 : 06 2005 Pid : 2752 MsgData : >> test2 需要提醒的是,由于 ACE_Log_Msg 是线程相关的,而且 spawn 出来的线程没有继承性,因此 Callback 仅对单个线程有效,如果想实现多个线程的 callback ,需要分别在各个线程中调用: ACE_LOG_MSG -> msg_callback ( callback );
5 . C / S 结构中输出到服务器
可用于分布式系统的日志处理( distributed logger ), logging server 运行在某台主机,并接收来自其它主机的 logging requests . 在其它主机(也可能在本机)需要运行一个 logging client daemon 进程,相当于一个 proxy ,实现了你自己编写的程序与 logging server 的交互。自己编写的程序格式如下:
#include < ace/Log_Msg.h >
int ACE_TMAIN ( int , ACE_TCHAR * argv []){ ACE_LOG_MSG -> open ( argv [ 0 ], ACE_Log_Msg :: LOGGER , ACE_DEFAULT_LOGGER_KEY );
ACE_DEBUG (( LM_DEBUG , ACE_TEXT ( "Sent to Logging Server/n" )));
return 0 ;}
在运行你自己编写的程序之前需要:
( 1 )首先运行 logging server :% ACE_ROOT %/ netsvcs / servers / main - f server . conf
( 2 )然后运行 logging client daemon :% ACE_ROOT %/ netsvcs / servers / main - f client . conf
其中 server . conf 内容如下: dynamic Logger Service_Object * ACE : _make_ACE_Logging_Strategy () "-s log.txt -f STDERR|OSTREAM" dynamic Server_Logging_Service Service_Object * netsvcs : _make_ACE_Server_Logging_Acceptor () active "-p 20009"
该文件每行以 dynamic 开始,第一行定义了 logging strategy ,将会把日志输出到 log . txt (- s 参数),同时输出到 STDERR 。第二行定义了 logging server 侦听( listen )端口为 20009 。
client . conf 内容如下: dynamic Client_Logging_Service Service_Object * netsvcs : _make_ACE_Client_Logging_Acceptor () active "-p 20009 -h localhost"
该文件同样以 dynamic 开始,定义了 logging client daemon 的侦听端口为 2009 (与 server . conf 一致),同时- h 指定目标机器名称或 ip (这里是本机)。
运行了 logging server 和 logging client daemon 之后,编译运行上面那个程序, logging server 会显示: Sent to Logging Server
同时在 logging server 所在目录(% ACE_ROOT %/ netsvcs / servers /)下会生成 log . txt ,内容是: starting up Logging Server at port 20009 on handle 1900Sent to Logging Server
注意到之所以如此麻烦地启动两级 logging 管理,主要是考虑到分布式处理过程中可能出现的瓶颈问题。
当然也可以直接通过 ACE_SOCK_Stream 实现与 logging server 的交互,而不用 logging client daemon ,细节以后讨论。而利用 server . conf 和 client . conf 来配置分布式 logging 服务涉及到了 ACE 的 Runtime Configuration ,细节同样在以后会讨论到。对其中参数的解释列举如下:
- f Specify ACE_Log_Msg flags ( OSTREAM , STDERR , LOGGER , VERBOSE , SILENT , VERBOSE_LITE ) used to control logging .- i The interval , in seconds , at which the log file size is sampled ( default is 0 ; do not sample by default ).- k Specify the rendezvous point for the client logger (比如 ACE_DEFAULT_LOGGER_KEY )- m The maximum log file size in Kbytes .- n Set the program name for the % n format specifier .- N The maximum number of log files to create .- o Request the standard log file ordering ( keeps multiple log files in numbered order ). Default is not to order log files .- p Pass in the processwide priorities to either enable ( DEBUG , INFO , WARNING , NOTICE , ERROR , CRITICAL , ALERT , EMERGENCY ) or to disable (~ DEBUG , ~ INFO , ~ WARNING , ~ NOTICE , ~ ERROR , ~ CRITICAL , ~ ALERT , ~ EMERGENCY ).- s Specify the file name used when OSTREAM is specified as an output target .- t Pass in the per instance priorities to either enable ( DEBUG , INFO , WARNING , NOTICE , ERROR , CRITICAL , ALERT , EMERGENCY ) or to disable (~ DEBUG , ~ INFO , ~ WARNING , ~ NOTICE , ~ ERROR , ~ CRITICAL , ~ ALERT , ~ EMERGENCY ).- w Cause the log file to be wiped out on both start - up and reconfiguration .
三 ACE 的重新定向
设置或改变 ACE 日志输出目标( logging sink )可以通过 ACE_Log_Msg 的方法 open 来完成,另外可通过 set_flags 和 clr_flags 来配合实现输出到多个目标。
open 方法的原型: /** * Initialize the ACE logging facility. Supplies the program name * that is available to each logging message call. Default arguments * set up logging to STDERR only. * * @param prog_name The name of the calling program. * @param options_flags A bitwise-or of options flags used to set the * initial behavior and logging sink(s). (see the * enum above for the valid values). * @param logger_key The name of ACE_FIFO rendezvous point where the * local client logger daemon is listening for logging * messages. Only meaningful if the LOGGER bit is * set in the @a flags argument. */ int open ( const ACE_TCHAR * prog_name , u_long options_flags = ACE_Log_Msg :: STDERR , const ACE_TCHAR * logger_key = 0 );
第一个参数 prog_name 表示程序名称,可以任意设置,可通过 ACE_Log_Msg 的 program_name 方法获取,另外当第二个参数设置中有 ACE_Log_Msg :: VERBOSE 时,会在输出信息前加上前缀,前缀中就包含该 program_name 。
第二个参数可以是: STDERR Write messages to STDERRLOGGER Write messages to the local client logger daemonOSTREAM Write messages to the assigned output streamMSG_CALLBACK Write messages to the callback objectVERBOSE Prepends program name , timestamp , host name , process ID , and message priority to each messageVERBOSE_LITE Prepends timestamp and message priority to each messageSILENT Do not print messages at allSYSLOG Write messages to the system 's event logCUSTOM Write messages to the user-provided back end
第三个参数logger key是针对第二个参数为LOGGER(C/S结构)时需要设置的,表示客户端程序端口值,比如:ACE_DEFAULT_LOGGER_KEY。
一旦调用了该方法,其后的输出将重新定位到第二个参数所指定的sink上。
set_flags、clr_flags的原型:
// Enable the bits in the logger' s options flags . void set_flags ( unsigned long f );
// Disable the bits in the logger's options flags.void clr_flags (unsigned long f);
参数含义同 open 函数的第二个参数 options_flags ,其中 set_flags 调用可在现有输出目标基础上增加新的输出目标(叠加), clr_flags 则从中删除指定的输出目标。
下面描述一下重定向到不同 sink 的例子。
1 .输出到 stderr
这个简单: ACE_LOG_MSG -> open ( argv [ 0 ], ACE_Log_Msg :: STDERR ); ACE_DEBUG (( LM_DEBUG , ACE_TEXT ( "test/n" )));
或者: ACE_LOG_MSG -> set_flags ( ACE_Log_Msg :: STDERR ); ACE_DEBUG (( LM_DEBUG , ACE_TEXT ( "test/n" )));
2 .输出到 System Logger
ACE_LOG_MSG -> open ( argv [ 0 ], ACE_Log_Msg :: SYSLOG , ACE_TEXT ( "ACE log" )); ACE_DEBUG (( LM_DEBUG , ACE_TEXT ( "test/n" )));
注意重新定向到 System Logger 不能用 set_flags 、 clr_flags 来实现。 Windows 操作系统下,会输出到系统的 Event Log 中,其中 Event Source 名称为 Open 函数第三个参数。 Unix / Linux 下会输出到 syslog facility 。另外 Windows 下 LM_STARTUP 、 LM_SHUTDOWN 、 LM_TRACE 、 LM_DEBUG 、 LM_INFO 会对应 EVENTLOG_INFORMATION_TYPE ; LM_NOTICE 、 LM_WARNING 会对应 EVENTLOG_WARNING_TYPE 、 LM_ERROR 、 LM_CRITICAL 、 LM_ALERT 、 LM_EMERGENCY 会对应 EVENTLOG_ERROR_TYPE 。
3 .输出到 Output Streams
下例将日志输出到文件( ofstream ):
#include < ace/Log_Msg.h >#include < ace/streams.h >
int ACE_TMAIN ( int , ACE_TCHAR * argv []){ ACE_OSTREAM_TYPE * output = new ofstream ( "test.txt" ); ACE_LOG_MSG -> msg_ostream ( output , 1 ); ACE_LOG_MSG -> set_flags ( ACE_Log_Msg :: OSTREAM ); ACE_LOG_MSG -> clr_flags ( ACE_Log_Msg :: STDERR ); ACE_DEBUG (( LM_DEBUG , ACE_TEXT ( "test/n" )));
return 0 ;}
上例中首先需要通过 msg_ostream 来 assign 一个 ACE OSTREAM ,然后再指定 log sink 为 ACE_Log_Msg :: OSTREAM ,指定 log sink 既可用 set_flags 也可用 open 方法,注意上例中 set_flags 之后紧接着又用 clr_flags 屏蔽掉先前指定的 ACE_Log_Msg :: STDERR (缺省 sink ),这样就不会同时输出到 stderr 了。
看一下 msg_ostream 的注释(解释的很明白,不赘述):
/** * delete_stream == 1, forces Log_Msg.h to delete the stream in * its own ~dtor (assumes control of the stream) * use only with proper ostream (eg: fstream), not (cout, cerr) */ void msg_ostream ( ACE_OSTREAM_TYPE *, int delete_ostream ); 上例中由于设置了 delete_stream == 1 ,所以不应再显示地调用 delete output ;来删除 ofstream 。 全局性的 ostream 还包括 cout 、 cerr 、 clog 等,这里再举一个输出到 cout 的例子,其它情况类似:
ACE_LOG_MSG -> msg_ostream (& cout ); ACE_LOG_MSG -> open ( argv [ 0 ], ACE_Log_Msg :: OSTREAM ); ACE_DEBUG (( LM_DEBUG , ACE_TEXT ( "test/n" )));
4 .输出到 Callback
在 ACE 中,将日志输出重新定向到回调函数其实很简单,只需要四步:
( 1 )定义 ACE_Log_Msg_Callback 的派生类,实现纯虚函数 virtual void log ( ACE_Log_Record & log_record ).
( 2 )在 ACE_Log_Msg 中注册该派生类(比如 MyCallback ): Callback * callback = new Callback ; ACE_LOG_MSG -> set_flags ( ACE_Log_Msg :: MSG_CALLBACK ); ACE_LOG_MSG -> clr_flags ( ACE_Log_Msg :: STDERR ); ACE_LOG_MSG -> msg_callback ( callback ); ( 3 )调用日志输出宏,比如 ACE_DEBUG ,就会将输出重新定向到 MyCallback 的 log 方法中。
( 4 )退出前的清理工作: ACE_LOG_MSG -> clr_flags ( ACE_Log_Msg :: MSG_CALLBACK ); delete callback ;
注意到 ACE_Log_Msg_Callback 的 log 方法的参数类型 ACE_Log_Record , 可以利用其 print 方法重新定制输出:
int print ( const ACE_TCHAR host_name [], u_long verbose_flag , FILE * fp );或者: int print ( const ACE_TCHAR host_name [], u_long verbose_flag , ACE_OSTREAM_TYPE & stream ); 第一个参数表示主机名,第二个参数可选 ACE_Log_Msg :: VERBOSE 、 VERBOSE_LITE 或 0 (原始信息),第三个参数可以是文件指针或者是标准输出流,比如:
log_record . print ( ACE_TEXT ( "" ), ACE_Log_Msg :: VERBOSE , cout ); /* 输出到屏幕 */ log_record . print ( ACE_TEXT ( "" ), 0 , ofstream ( "test.txt" , ios :: app )); /* 输出到文件 */
关于 ACE_Log_Record 进一步使用,请参考以下例子:
/* main.cpp */#include < ace/Task.h >#include < ace/Log_Msg.h >#include " MyCallback.h "
int ACE_TMAIN ( int , ACE_TCHAR *[]){ MyCallback * callback = new MyCallback ;
ACE_LOG_MSG -> set_flags ( ACE_Log_Msg :: MSG_CALLBACK ); ACE_LOG_MSG -> clr_flags ( ACE_Log_Msg :: STDERR ); ACE_LOG_MSG -> msg_callback ( callback );
ACE_DEBUG (( LM_DEBUG , ACE_TEXT ( "test1/n" ))); ACE_DEBUG (( LM_INFO , ACE_TEXT ( "test2/n" )));
ACE_LOG_MSG -> clr_flags ( ACE_Log_Msg :: MSG_CALLBACK ); delete callback ;
return 0 ;}
/* MyCallback.h */#include < ace/streams.h >#include < ace/Log_Msg.h >#include < ace/Log_Msg_Callback.h >#include < ace/Log_Record.h >#include < ace/streams.h >#include < ace/Log_Msg_Callback.h >#include < ace/Log_Record.h >#include < ace/SString.h >#include < ace/OS.h >
class MyCallback : public ACE_Log_Msg_Callback { public : void log ( ACE_Log_Record & log_record ) { cerr << "Log Message Received:" << endl ; unsigned long msg_severity = log_record . type ();
ACE_Log_Priority prio = ACE_static_cast ( ACE_Log_Priority , msg_severity ); const ACE_TCHAR * prio_name = ACE_Log_Record :: priority_name ( prio ); cerr << "/tType: " << ACE_TEXT_ALWAYS_CHAR ( prio_name ) << endl ;
cerr << "/tLength: " << log_record . length () << endl ;
const time_t epoch = log_record . time_stamp (). sec (); cerr << "/tTime_Stamp: " << ACE_TEXT_ALWAYS_CHAR ( ACE_OS :: ctime (& epoch )) << flush ;
cerr << "/tPid: " << log_record . pid () << endl ;
ACE_CString data ( ">> " ); data += ACE_TEXT_ALWAYS_CHAR ( log_record . msg_data ());
cerr << "/tMsgData: " << data . c_str () << endl ; }};
输出: Log Message Received : Type : LM_DEBUG Length : 32 Time_Stamp : Mon Mar 27 17 : 03 : 06 2005 Pid : 2752 MsgData : >> test1
Log Message Received : Type : LM_INFO Length : 32 Time_Stamp : Mon Mar 27 17 : 03 : 06 2005 Pid : 2752 MsgData : >> test2 需要提醒的是,由于 ACE_Log_Msg 是线程相关的,而且 spawn 出来的线程没有继承性,因此 Callback 仅对单个线程有效,如果想实现多个线程的 callback ,需要分别在各个线程中调用: ACE_LOG_MSG -> msg_callback ( callback );
5 . C / S 结构中输出到服务器
可用于分布式系统的日志处理( distributed logger ), logging server 运行在某台主机,并接收来自其它主机的 logging requests . 在其它主机(也可能在本机)需要运行一个 logging client daemon 进程,相当于一个 proxy ,实现了你自己编写的程序与 logging server 的交互。自己编写的程序格式如下:
#include < ace/Log_Msg.h >
int ACE_TMAIN ( int , ACE_TCHAR * argv []){ ACE_LOG_MSG -> open ( argv [ 0 ], ACE_Log_Msg :: LOGGER , ACE_DEFAULT_LOGGER_KEY );
ACE_DEBUG (( LM_DEBUG , ACE_TEXT ( "Sent to Logging Server/n" )));
return 0 ;}
在运行你自己编写的程序之前需要:
( 1 )首先运行 logging server :% ACE_ROOT %/ netsvcs / servers / main - f server . conf
( 2 )然后运行 logging client daemon :% ACE_ROOT %/ netsvcs / servers / main - f client . conf
其中 server . conf 内容如下: dynamic Logger Service_Object * ACE : _make_ACE_Logging_Strategy () "-s log.txt -f STDERR|OSTREAM" dynamic Server_Logging_Service Service_Object * netsvcs : _make_ACE_Server_Logging_Acceptor () active "-p 20009"
该文件每行以 dynamic 开始,第一行定义了 logging strategy ,将会把日志输出到 log . txt (- s 参数),同时输出到 STDERR 。第二行定义了 logging server 侦听( listen )端口为 20009 。
client . conf 内容如下: dynamic Client_Logging_Service Service_Object * netsvcs : _make_ACE_Client_Logging_Acceptor () active "-p 20009 -h localhost"
该文件同样以 dynamic 开始,定义了 logging client daemon 的侦听端口为 2009 (与 server . conf 一致),同时- h 指定目标机器名称或 ip (这里是本机)。
运行了 logging server 和 logging client daemon 之后,编译运行上面那个程序, logging server 会显示: Sent to Logging Server
同时在 logging server 所在目录(% ACE_ROOT %/ netsvcs / servers /)下会生成 log . txt ,内容是: starting up Logging Server at port 20009 on handle 1900Sent to Logging Server
注意到之所以如此麻烦地启动两级 logging 管理,主要是考虑到分布式处理过程中可能出现的瓶颈问题。
当然也可以直接通过 ACE_SOCK_Stream 实现与 logging server 的交互,而不用 logging client daemon ,细节以后讨论。而利用 server . conf 和 client . conf 来配置分布式 logging 服务涉及到了 ACE 的 Runtime Configuration ,细节同样在以后会讨论到。对其中参数的解释列举如下:
- f Specify ACE_Log_Msg flags ( OSTREAM , STDERR , LOGGER , VERBOSE , SILENT , VERBOSE_LITE ) used to control logging .- i The interval , in seconds , at which the log file size is sampled ( default is 0 ; do not sample by default ).- k Specify the rendezvous point for the client logger (比如 ACE_DEFAULT_LOGGER_KEY )- m The maximum log file size in Kbytes .- n Set the program name for the % n format specifier .- N The maximum number of log files to create .- o Request the standard log file ordering ( keeps multiple log files in numbered order ). Default is not to order log files .- p Pass in the processwide priorities to either enable ( DEBUG , INFO , WARNING , NOTICE , ERROR , CRITICAL , ALERT , EMERGENCY ) or to disable (~ DEBUG , ~ INFO , ~ WARNING , ~ NOTICE , ~ ERROR , ~ CRITICAL , ~ ALERT , ~ EMERGENCY ).- s Specify the file name used when OSTREAM is specified as an output target .- t Pass in the per instance priorities to either enable ( DEBUG , INFO , WARNING , NOTICE , ERROR , CRITICAL , ALERT , EMERGENCY ) or to disable (~ DEBUG , ~ INFO , ~ WARNING , ~ NOTICE , ~ ERROR , ~ CRITICAL , ~ ALERT , ~ EMERGENCY ).- w Cause the log file to be wiped out on both start - up and reconfiguration .