1. zlog简介
zlog的资料网上很多,这里不在详细说明;zlog是用c写的一个日志工具,非常小,而且高效,可以同时向控制台和文件中输出,日志接口与printf使用基本一样,所以使用起来很简单。
感觉唯一的缺点是配置稍微复杂点,不能动态修改输出级别
2.使用介绍
2.1 zlog编译
zlog的很好编译,如果你是在x86平台上,就不用修改makefile,进入src目录下直接make就可以了;
如果是在交叉编译,移植到嵌入式设备上用,那么只需要修改src/makefile里的cc为交叉编译器的gcc,还有一处ar修改为交叉编译器的ar:
然后make,一般都可以直接编译过,编译结束后,在src目录下生成两个库文件:
libzlog.so和libzlog.a
2.2 zlog配置文件
zlog使用时,需要先配置一下输出规则,需要写在一个文件里;下面简单介绍一下配置文件。
配置文件*.conf 配置文件具体内容如下: [global] #改变量可以不写,默认是true,如果使用设置为true时,Zlog就会严格检查所用格式和规则,否则,忽略所用格式和规则。 strict init = true buffer min = 1024 buffer max = 2048 #转档指定锁文件,用于保证多进程下日志安全转档,使用默认的配置文件为锁文件。 #rotate lock file = zlog.lock #日志访问权限,600 只允许当前用户访问 file perms = 600 [formats] #使用默认日志输出格式 "%d %V [%p %F %L] %m%n" 输出日志格式为:%-5V按照日志级别按照左对齐 #2012-12-13 10:23:29 INFO [31668:test_hello.c:41] hello, zlog simple = "%d.%-8.8us %-5V [%-8.8p.%-8.8t %F %L] %m%n" #simple = "%d.%ms %m%n" #simple2 = "%d.%us %m%n" [rules] #优先级从低到高 debug info notice warn fatal debug大于等于debug的优先级都能给通过debug输出。 my_cat.* >stderr; #当hello.txt文件大小大于10MB时,会将hello.txt->hello.txt.0 0代表不删除任何文件 my_cat.INFO "hello.txt",10kb * 3 ~ "hello.txt.#r";simple #my_cat.INFO "hello.txt",1MB ~ "hello-%d(%Y%m%d).#2s.txt";simple #my_cat.INFO "hello.txt",1MB;simple #my_cat.INFO "hello.txt",1MB;simple
2.3 zlog使用
zlog使用时首先要初始化配置,然后获取到一个句柄(指针),由于这个句柄是全局的,这在c中很正常,但是用c++久了,都不喜欢全局变量了,所以这里我用c++的单实例思想,把zlog初始化这部分封装了一下,这样用起来也简单,只需要把这两个文件包含进去,安照自己的需要,修改一下里面日志的路径和cat即可:
源文件log_manager.cpp:
#include <stdlib.h> #include <stdio.h> #include <string.h> #include <unistd.h> #include <sys/stat.h> #include <sys/types.h> #include <dirent.h> #include "log_manager.h" /*********************************************************/ /*常量****************************************************/ const char* ConfigText = "[global]\n" "strict init = true\n" "buffer min = 1024\n" "buffer max = 2048\n" "#日志访问权限,600 只允许当前用户访问\n" "file perms = 600\n" "[formats]\n" "simple = \"%d.%-8.8us %-5V [%-8.8p.%-8.8t %F %L] %m%n\"\n" "simple1= \"%m%n\"\n" "[rules]\n" "db_cat.warn >stderr;simple1\n" "db_cat.ERROR \"./logs/test.txt\",1M * 3 ~ \"./logs/test.txt.#r\";simple\n"; //优先级从低到高 debug info notice warn error fatal debug大于等于debug的优先级都能给通过debug输出。 /*********************************************************/ static zlog_category_t * logHandler_m = NULL; static int DetectConfigFile(const char *File); /***************************************************************************** 函 数 名 : LogMgr.LogMgr 功能描述 : 日志模块初始化 输入参数 : 无 输出参数 : 无 返 回 值 : 修改历史 : 1.日 期 : 2012年12月19日 星期三 作 者 : fensjoy 修改内容 : 新生成函数 *****************************************************************************/ zlog_category_t * Init_zlog() { DetectConfigFile(LOG_CONFIG); zlog_init(LOG_CONFIG); logHandler_m = zlog_get_category(LOG_CAT); if (!logHandler_m) { printf("%s in Init_zlog, get cat fail! line = %d\n",PRO_NAME, __LINE__); zlog_fini(); remove(LOG_CONFIG); exit(-1); } return logHandler_m; }; /***************************************************************************** 函 数 名 : DetectConfigFile 功能描述 : 检测日志模块的配置文件是否存在,不存在则创建 输入参数 : const char *File 输出参数 : 无 返 回 值 : static 修改历史 : 1.日 期 : 2012年12月20日 星期四 作 者 : fensjoy 修改内容 : 新生成函数 *****************************************************************************/ static int DetectConfigFile(const char *File) { FILE *fp = NULL; int iRet = 0; DIR *log_p = NULL; char *cmd_buf = NULL; /*判断日志文件保存目录是否存在,不存在则创建*/ log_p = opendir(LOG_PATH); if ( log_p == NULL ) { printf("%s in DetectConfigFile, the log dir is not exist, now creat: %s!\n", PRO_NAME,LOG_PATH); cmd_buf = new char[64]; printf("%s in DetectConfigFile, the log dir is not exist, now creat!\n", PRO_NAME); snprintf(cmd_buf, 64, "mkdir -p %s &", LOG_PATH); iRet = system(cmd_buf); delete [] cmd_buf; } else { closedir(log_p); } if ( access(File, F_OK) != 0 ) { printf("%s log config file not exist,now creat!\n", PRO_NAME); fp = fopen(File, "w+"); if(fp == NULL) { perror("#[db]: in DetectConfigFile, fopen config file error!"); return -1; } iRet = fwrite(ConfigText, 1, strlen(ConfigText), fp); if ( iRet < 0 ) { perror("#[para]: in DetectConfigFile, fwrite error!"); fclose(fp); return -1; } fclose(fp); } return 0; } /***************************************************************************** 函 数 名 : getZlogHandler 功能描述 : 获取zlog日志句柄 输入参数 : 无 输出参数 : 无 返 回 值 : zlog_category_t 修改历史 : 1.日 期 : 2014年1月24日 星期五 作 者 : fensjoy 修改内容 : 新生成函数 *****************************************************************************/ zlog_category_t * getZlogHandler() { if ( NULL == logHandler_m ) { logHandler_m = Init_zlog(); } return logHandler_m; }
头文件log_manager.h
/****************************************************************************** 版权所有 (C), 2001-2014, ****************************************************************************** 文 件 名 : log_manger.h 版 本 号 : 初稿 作 者 : fensjoy 生成日期 : 2013年6月5日 星期三 最近修改 : 功能描述 : log_manger.cpp 的头文件 函数列表 : 修改历史 : 1.日 期 : 2013年6月5日 星期三 作 者 : fensjoy 修改内容 : 创建文件 ******************************************************************************/ #ifndef __LOG_MANGER_H__ #define ___LOG_MANGER_H__ #include <iostream> #include "zlog.h" #define PRO_NAME "#[db]: " #define LOG_CONFIG "./test_log.conf" #define LOG_PATH "./" #define LOG_CAT "test_cat" //注意这里要与配置文件中保持一致,否则无法输出 //extern zlog_category_t * logHandler_m; zlog_category_t * Init_zlog(); zlog_category_t * getZlogHandler(); #endif /* __LOG_MANGER_H__ */
测试main函数:
#include <iostream> #include "log_manager.h" using namespace std; int main(int argc, char **argv) { zlog_category_t *pLog = Init_zlog(); zlog_notice(pLog, "hello zlog!"); zlog_error(pLog, "this msg both to console and log file!"); zlog_debug(pLog, "this msg is debug level, just to console!"); return 0; }
是不是很简单~;
make 编译后直接运行:
运行:
log文件内容:
用起来确实很简单,我感觉zlog比较适合用于程序的性能分析,即程序长时间运行时,记录程序运行状态,然后分析程序性能,以便于后期优化;另外zlog有个地方需要注意下,就是在日志文件达到设置的大小时,切换日志文件,如果这时程序输出日志过多间隔也比较短(100毫秒)左右时,程序会挂掉,这时zlog的一个bug。一般程序输出日志没那么多时,不会出现
源代码已上传CSDN:
https://download.csdn.net/download/wuquan_1230/10931319