残剑

Stop walking today and you'll have to run tomorrow!

RobotsBrain: Log输出

| Comments

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

1
2
3
4
5
6
7
8
9
10
11
12
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__等信息,其具体的实现如下所示:

1
2
3
4
5
6
7
8
9
#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)

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#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的值设置的越小,它输出的信息越多:

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

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

1
void rb_log_uninit(void);

检测是否要打印信息:

1
int rb_log_check_level(log_level level);

日志输出:

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

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

Comments