在构建一个库的时候,通常会写专门的log输出函数,下面介绍一个简单的实现。根据不同的需求,需要对日志的输出作一个级别限定,便于查阅及跟踪流程。以下是对级别的设置:

typedef enum log_level_en {
    RB_LOG_MIN,
    RB_LOG_DEBUG,
    RB_LOG_INFO,
    RB_LOG_NOTICE,
    RB_LOG_WARNING,
    RB_LOG_ERROR,
    RB_LOG_CRIT,
    RB_LOG_ALERT,
    RB_LOG_EMERG,
    RB_LOG_MAX
}log_level;

该部分参考内核的级别设定,不同的是数值越低其信息的重要程度越低。

具体的日志输出,我们采用了宏定义的方式,因为考虑到要输出__FUNCTION__等信息,其具体的实现如下所示:

#define RB_LOG(level, fmt, args...) \
    do {    \
        if(rb_log_check_level(level) == 0)  \
            break;  \
        char rb_log_buf[RB_LOG_BUFFER_LEN] = {0};   \
        snprintf(rb_log_buf, RB_LOG_BUFFER_LEN, "pid(%d) %s %s(%d)", \
                    getpid(), __FILE__, __FUNCTION__, __LINE__);    \
        rb_log_printf(level, rb_log_buf, fmt, ##args);  \
    } while(0)

每个级别输出的宏定义如下:

#define RB_DEBUG(fmt, args...)  RB_LOG(RB_LOG_DEBUG, fmt, ##args)

#define RB_INFO(fmt, args...)   RB_LOG(RB_LOG_INFO, fmt, ##args)

#define RB_NOTICE(fmt, args...) RB_LOG(RB_LOG_NOTICE, fmt, ##args)

#define RB_WARNING(fmt, args...)    RB_LOG(RB_LOG_WARNING, fmt, ##args)

#define RB_ERROR(fmt, args...)  RB_LOG(RB_LOG_ERROR, fmt, ##args)

#define RB_CRIT(fmt, args...)   RB_LOG(RB_LOG_CRIT, fmt, ##args)

#define RB_ALERT(fmt, args...)  RB_LOG(RB_LOG_ALERT, fmt, ##args)

#define RB_EMERG(fmt, args...)  RB_LOG(RB_LOG_EMERG, fmt, ##args)

初始化函数,用于设置输出文件的名称和输出级别的设定:如果log_file设置成NULL的话,则直接将信息打印到stderrlevel的值设置的越小,它输出的信息越多:

void rb_log_init(const char *log_file, log_level level);

释放分配的资源,如果调用了rb_log_init就必须调用以下的接口:

void rb_log_uninit(void);

检测是否要打印信息:

int rb_log_check_level(log_level level);

日志输出:

void rb_log_printf(log_level level, const char *prefix, const char *fmt, ...);

当然我们也可以直接调用RB_DEBUG等接口,这样的话,log信息直接输出到stderr。具体的代码及测试用例,请参考这里


txgcwm
764 声望71 粉丝

Linux C/C++