c语言编写分级别打印的日志系统 linux环境

前面的描述可能不够好,毕竟文字水平有限,有些东西太难用文字表达,大家可以直接看代码,代码里有着注释

宏定义控制级别的实现

这个日志系统我是通过宏定义来进行分级别打印的,为什么选择在编译前实现分级别,而不是在编译后用函数接口来实现分级别打印的。两者各有各的优点,前者能够带来比较好的效率,级别的比较都是通过预处理来执行的,这样在运行过程中会省下一部分时间,然而如果使用第二种是不是一但需要的打印的东西多了,程序就要不断的调用函数,这样显然浪费很多时间,但是这样比较便捷灵活,各有各的好处。

首先我们要了解宏定义以及##粘合剂和可变变参宏__VA_ARGS__,相信大家的对于宏定义的基本用法大概都知道,这里我们将了解下##粘合剂和变参宏。

##粘合剂

##运算符可用于类函数宏的替换部分,而且,##还可用于对象宏的替换部分, ##运算符把两个记号组合成一个记号。例如下面伪代码

#define NAME(n)  x ## n

int  NAME(1)  = 14;  变成 int x1 = 14;
int  NAME(2)  = 14;  变成 int x2 = 14;

简单来所就是把x和n都来个的值合在一起,

变参宏…和__VA+ARGS__

这种灵活的定义宏的方式,给了我们极大的便利, 能够让我们不用限制宏函数的参数的类型和个数,编译器会自动适配,如下面

#define  PR(...) printf(__VA_ARGS__)

PR("howday");
PR("weight = %d, shipping = $%.2f\n", wt, sp);

对于第一次调用,__VA_ARGS__展开为1个参数:“howday"
对于第一次调用,__VA_ARGS__展开为2个参数:“weight = %d, shipping = $%.2f\n”、 wt、 sp

所以,展开的代码为
printf("howday");
printf("weight = %d, shipping = $%.2f\n", wt, sp);

运用上面两个技巧我们可以完成下面分级别部分的宏定义

宏定义级别输入代码

/*-----------------------------------------------------------------------------
 *  打印输出级别
 *-----------------------------------------------------------------------------*/
#define DEBUG         5
#define ENTRY         4
#define INFO          3
#define WARN          2
#define ERROR         1
#define NONE          0


/*-----------------------------------------------------------------------------
 *  如果在编译阶段不定义PRINT_LEVEL,则默认DEBUG模式打印,如果用-D PRINT_LEVEL=?
 *  则在某个级别模式下打印,如下列:gcc log.c -D PRINT_LEVEL=INFO(或者是对应得数字)
 *  则在INFO模式下打印。
 *-----------------------------------------------------------------------------*/
#ifndef PRINT__LEVEL
#define DEBUG_LEVEL INFO   //默认级别
#else
#define DEBUG_LEVEL PRINT__LEVEL
#endif
 

#define LOG_DEBUG(args,...)\
    do{\
             if (DEBUG_LEVEL >= DEBUG)\
             {\
                        printf("[D] (%s, %d) "args"", __FILE__, __LINE__, ##__VA_ARGS__);\
                    }\
     }while(0)

#define LOG_ENTRY(args,...)\
    do{\
            if (DEBUG_LEVEL >= ENTRY)\
            {\
                        printf("[L] (%s, %d) "args"", __FILE__, __LINE__, ##__VA_ARGS__);\
                    }\
    }while(0)

#define LOG_INFO(args,...)\
    do{\
            if (DEBUG_LEVEL >= INFO)\
            {\
                        printf("[I] (%s, %d) "args"", __FILE__, __LINE__, ##__VA_ARGS__);\
                    }\
    }while(0)

#define LOG_WARN(args,...)\
    do{\
            if (DEBUG_LEVEL >= WARN)\
            {\
                        printf("[W] (%s, %d) "args"", __FILE__, __LINE__, ##__VA_ARGS__);\
                    }\
    }while(0)

#define LOG_ERROR(args,...)\
    do{\
            if (DEBUG_LEVEL >= ERROR)\
            {\
                        printf("[E] (%s, %d) "args"", __FILE__, __LINE__, ##__VA_ARGS__);\
                    }\
    }while(0)

#define LOG_NONE(args,...)\
    do{\
            if (DEBUG_LEVEL >= NONE)\
            {\
                        printf("[N] (%s, %d) "args"", __FILE__, __LINE__, ##__VA_ARGS__);\
                    }\
    }while(0)

这样我们就完成了级别的控制,首先我们定义了六种打印级别,安大到小一一排列,根据大小比较来进行打印的控制,下面代码的这一部分是为了设置默认级别的,如果不进行修改就按默认级别及其比它小的级别打印输出,我们可以在编译阶段通过gcc -D 选项中改变默认级别,具体可参考注释

#ifndef PRINT__LEVEL
#define DEBUG_LEVEL INFO   //默认级别
#else
#define DEBUG_LEVEL PRINT__LEVEL
#endif

这样就完成了级别的控制。

选择输出的地方
标准打印输出

这个没什么好说的,

日志文件的输出

日志文件的输出,我们首先要判断文件存不存在,用access函数可以实现这一功能,如果不存在我们就要创建这个文件,直接掉要open函数或者creat函数创建函数是不可取,因为创建的文件的文件屏蔽掩码一般默认为002,也就是会组织其它用户的写入文件,可在命令行中查看所以我们可以在创建文件前使用umask函数先设置好屏蔽为,具体的细节可以查看UNIX环境高级编程这本书,
调用open函数时记得一定又有O_APPEND这个选项,不然每次写都不会追加在后面的,
如果我们想知道上次进入和上次进入并且修改了文件的时间,我们可以使用fstat这个函数,它记录了文件的一些信息,然后就可以打印时间信息</

  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值