2008年6月20日 星期五

ortp log architecture

ortp provide the logging apis for application using include
* ortp_log
* ortp_message
* ortp_warning
* ortp_error
* ortp_fatal

defined in the include/ortp/ortp.h
#ifdef ORTP_NOMESSAGE_MODE
#define ortp_log(...)
#define ortp_message(...)
#define ortp_warning(...)
#else
static inline void ortp_log(OrtpLogLevel lev, const char *fmt,...){
va_list args;
va_start (args, fmt);
ortp_logv(lev, fmt, args);
va_end (args);
}
[omit]
#endif

So if the compiler option (Makefile or header file) of application program doesn't define "ORTP_NOMESSAGE_MODE", than the ortp_log/ortp_message/ortp_warning will real output the logging messages

The function of real logging message is ortp_logv(lev, fmt, args)

let's look inside this function

include/ortp/ortp.h
#if !defined(WIN32) && !defined(_WIN32_WCE)
#define ortp_logv(level,fmt,args) \
{\
if (ortp_logv_out!=NULL && ortp_log_level_enabled(level)) \
ortp_logv_out(level,fmt,args);\
if ((level)==ORTP_FATAL) abort();\
}while(0)
#else
void ortp_logv(int level, const char *fmt, va_list args);
#endif

Currently we only focus on the linux platform. The ortp_logv was defined as a macro. It will make sure the ortp_logv_out is not a NULL function and the specified level is matched with the user preset level mask. And then the specified level log will output by the ortp_logv_out function.


Let's look inside the ortp_logv_out function
src/ortp.c
static void __ortp_logv_out(OrtpLogLevel lev, const char *fmt, va_list args);
OrtpLogFunc ortp_logv_out=__ortp_logv_out;
/**
*@param func: your logging function, compatible with the OrtpLogFunc prototype.
*
**/
void ortp_set_log_handler(OrtpLogFunc func){
ortp_logv_out=func;
}

the ortp_logv_out (which is the type of function pointer) was originally hardcode assign to the __ortp_logv_out. And the ortp_logv_out can be dynamically changed by the ortp_set_log_handle api to the user new defined logging function.

Let's look inside the __ortp_logv_out function in details

static void __ortp_logv_out(OrtpLogLevel lev, const char *fmt, va_list args){
const char *lname="undef";
char *msg;
if (__log_file==NULL) __log_file=stderr;
switch(lev){
case ORTP_DEBUG:
lname="debug";
break;
case ORTP_MESSAGE:
lname="message";
break;
case ORTP_WARNING:
lname="warning";
break;
case ORTP_ERROR:
lname="error";
break;
case ORTP_FATAL:
lname="fatal";
break;
default:
ortp_fatal("Bad level !");
}
msg=_strdup_vprintf(fmt,args);
fprintf(__log_file,"ortp-%s-%s" ENDLINE,lname,msg);
ortp_free(msg);
}

Finally __ortp_logv_out will output the api message to the specified direction (either FILE or stderr).


Additionally you can use ortp_set_log_file to change the api message output to the file descriptor (the default __log_file is set to NULL, so the api message will output to the stderr)
static FILE *__log_file=0;

/**
*@param file a FILE pointer where to output the ortp logs.
*
**/
void ortp_set_log_file(FILE *file)
{
__log_file=file;
}

沒有留言: