三个文件,一个path.c、一个log.h、一个log.c都在下面;
path.c
#include <stddef.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
#define MAX_NAME 256
static char root_path[MAX_NAME] = {"TSC_ROOT not init"};
static char app_name[MAX_NAME] = {0};
void tsc_path_init()
{
char* root = getenv("TSC_ROOT");
if(root != NULL)
{
strncpy(root_path,root,sizeof(root_path)-1);
}
}
const char* tsc_path()
{
return (const char*)root_path;
}
static int file_read(const char* path,char* out,int out_len)
{
int fd = open(path,O_RDONLY);
if(fd == -1)
return errno;
int rt = read(fd,out,out_len);
close(fd);
return rt;
}
const char* tsc_app_name()
{
if(app_name[0] != ' ')
return app_name;
int pid = getpid();
char path[256];
sprintf(path,"/proc/%d/cmdline",pid);
int len = file_read(path,path,sizeof(path));
if(len<=0)
return NULL;
char* ptr = (char*)path+len;
while(ptr!=path&&*ptr!='/')
ptr--;
ptr = (*ptr=='/')?(ptr+1):ptr;
strncpy(app_name,ptr,sizeof(app_name)-1);
return (const char*)app_name;
}
hal.h
#ifndef __TSC_HAL_log_H_
#define __TSC_HAL_log_H_
#ifdef TSC_X86
#include <stdio.h>
#else
#endif
#ifdef __cplusplus
extern "C" {
#endif
enum {
TSC_LOG_NONE = 0, /* No log. */
TSC_LOG_EMERG = 1, /* System is unusable. */
TSC_LOG_ALERT = 2, /* Action must be taken immediately.*/
TSC_LOG_CRIT = 3, /* Critical conditions. */
TSC_LOG_ERROR = 4, /* Error conditions. */
TSC_LOG_WARNING = 5, /* Warning conditions. */
TSC_LOG_NOTICE = 6, /* Normal but significant condition.*/
TSC_LOG_INFO = 7, /* Infomational. */
TSC_LOG_DEBUG = 8, /* Debug-level message. */
TSC_LOG_ALL = 9 /* All log. */
};
#ifdef TSC_X86
extern int tsc_log_level;
#else
#endif
/*
* set the rolling log
* @param f_size
* log file max size
* @param f_num
* log file max number
* @param dir
* log file output directory
* @param prefix
* log file name
*/
void tsc_log_init(int f_size,int f_num,char* log_dir,char* log_prefix);
void tsc_log_fini();
static inline int tsc_log_level_set(int level)
{
if(level >= TSC_LOG_NONE && level <= TSC_LOG_ALL)
{
tsc_log_level = level;
return 0;
}
return -1;
}
static inline int tsc_log_level_get(void)
{
return tsc_log_level;
}
void tsc_debug(const char* fmt,...);
void tsc_info(const char* fmt,...);
void tsc_notice(const char* fmt,...);
void tsc_warn(const char* fmt,...);
void tsc_error(const char* fmt,...);
void tsc_crit(const char* fmt,...);
void tsc_alert(const char* fmt,...);
void tsc_emerg(const char* fmt,...);
#ifdef __cplusplus
}
#endif
#endif //_TSC_HAL_LOG_H_
hal.c
#include <unistd.h>
#include <assert.h>
#include <stdio.h>
#include <stdarg.h>
#include "log4c.h"
#include "log4c/rollingpolicy_type_sizewin.h"
#include "tsc_hal_log.h"
extern const char* tsc_path();
extern const char* tsc_app_name();
int tsc_log_level = TSC_LOG_ALL;
log4c_category_t* __log4c_category__ = NULL;
log4c_appender_t* __log4c_appender__ = NULL;
rollingfile_udata_t* __log4c_rf__ = NULL;
log4c_rollingpolicy_t* __log4c_rp__ = NULL;
rollingpolicy_sizewin_udata_t* __log4c_sw__ = NULL;
log4c_layout_t* __log4c_layout__ = NULL;
const char* __log_prefix__ = "log";
/********************************** log4cpp ******************************************/
extern rollingfile_udata_t* rollingfile_make_udata(void);
extern int rollingfile_udata_set_logdir(rollingfile_udata_t* rfudatap,const char* logdir);
extern int rollingfile_udata_set_files_prefix(rollingfile_udata_t *rfudatap,const char* prefix);
extern int rollingfile_udata_set_policy(rollingfile_udata_t* rfudatap,log4c_rollingpolicy_t* policyp);
extern const log4c_layout_type_t log4c_layout_type_dated_r;
extern const log4c_appender_type_t log4c_appender_type_rollingfile;
/*************************************************************************************/
/**************************************************
* 函数名称 : tsc_log_init
* 函数功能 : 日志功能初始化
* 输 入 : f_size @单个文件大小; f_num @留存文件数量
* log_dir @日志存放目录; log_prefix 日志后缀
* 输 出 :
* 返 回 :
* 作 者 :
* 创建日期 : 2016/08/25
* 其他说明 :
**************************************************/
void tsc_log_init(int f_size,int f_num,char* log_dir,char* log_prefix)
{
//如果传入的参数为空那么按照特定方式去组织一个目录
if(log_dir == NULL)
{
char _log_dir[1024];
assert(tsc_path() != NULL);
assert(tsc_app_name() != NULL);
snprintf(_log_dir,sizeof(_log_dir)-1,"%s/log/%s",tsc_path(),tsc_app_name());
log_dir = _log_dir;
}
//参数检查,为空则设置为默认的后缀格式
if(log_prefix == NULL)
{
log_prefix = (char*)__log_prefix__;
}
if(__log4c_category__ == NULL)
{
//建立category对象
assert((__log4c_category__ = log4c_category_new("")) != NULL);
//建立appender对象
assert((__log4c_appender__ = log4c_appender_new("tsc_log_appender")) != NULL);
//文件循环方式,切换条件
assert((__log4c_rf__ = rollingfile_make_udata()) != NULL);
assert((__log4c_rp__ = log4c_rollingpolicy_new("tsc_log_rfpolicy")) != NULL);
assert((__log4c_sw__ = sizewin_make_udata()) != NULL);
//新建layout
assert((__log4c_layout__ = log4c_layout_new("tsc_log_layout")) != NULL);
//为category设置优先级,设置appender
log4c_category_set_priority(__log4c_category__,LOG4C_PRIORITY_DEBUG);
log4c_category_set_appender(__log4c_category__,__log4c_appender__);
//将建好的appender进行实例化
log4c_appender_set_type(__log4c_appender__,&log4c_appender_type_rollingfile);
log4c_appender_set_udata(__log4c_appender__,__log4c_rf__);
//设置文件循环策略属性
rollingfile_udata_set_logdir(__log4c_rf__,log_dir);
rollingfile_udata_set_files_prefix(__log4c_rf__,log_prefix);
rollingfile_udata_set_policy(__log4c_rf__,__log4c_rp__);
//设置日志文件切换条件
log4c_rollingpolicy_set_udata(__log4c_rp__,__log4c_sw__);
sizewin_udata_set_file_maxsize(__log4c_sw__,f_size);
sizewin_udata_set_max_num_files(__log4c_sw__,f_num);
//实例化layout,并与appender进行绑定
log4c_rollingpolicy_init(__log4c_rp__,__log4c_rf__);
log4c_layout_set_type(__log4c_layout__,&log4c_layout_type_dated_r);
log4c_appender_set_layout(__log4c_appender__,__log4c_layout__);
}
}
void tsc_log_fini()
{
if(__log4c_category__ != NULL)
{
log4c_category_delete(__log4c_category__);
}
if(__log4c_appender__ != NULL)
{
log4c_appender_delete(__log4c_appender__);
}
if(__log4c_rp__ != NULL)
{
log4c_rollingpolicy_delete(__log4c_rp__);
}
if(__log4c_layout__ != NULL)
{
log4c_layout_delete(__log4c_layout__);
}
}
void tsc_debug(const char* fmt,...)
{
if(tsc_log_level >= TSC_LOG_DEBUG)
{
va_list argptr;
va_start(argptr,fmt);
log4c_category_vlog(__log4c_category__,LOG4C_PRIORITY_DEBUG,fmt,argptr);
va_end(argptr);
}
}
void tsc_info(const char* fmt,...)
{
if(tsc_log_level >= TSC_LOG_INFO)
{
va_list argptr;
va_start(argptr,fmt);
log4c_category_vlog(__log4c_category__,LOG4C_PRIORITY_INFO,fmt,argptr);
va_end(argptr);
}
}
void tsc_notice(const char* fmt,...)
{
if(tsc_log_level >= TSC_LOG_NOTICE)
{
va_list argptr;
va_start(argptr,fmt);
log4c_category_vlog(__log4c_category__,LOG4C_PRIORITY_NOTICE,fmt,argptr);
va_end(argptr);
}
}
void tsc_warn(const char* fmt,...)
{
if(tsc_log_level >= TSC_LOG_WARNING)
{
va_list argptr;
va_start(argptr,fmt);
log4c_category_vlog(__log4c_category__,LOG4C_PRIORITY_WARN,fmt,argptr);
va_end(argptr);
}
}
void tsc_error(const char* fmt,...)
{
if(tsc_log_level >= TSC_LOG_ERROR)
{
va_list argptr;
va_start(argptr,fmt);
log4c_category_vlog(__log4c_category__,LOG4C_PRIORITY_ERROR,fmt,argptr);
va_end(argptr);
}
}
void tsc_crit(const char* fmt,...)
{
if(tsc_log_level >= TSC_LOG_CRIT)
{
va_list argptr;
va_start(argptr,fmt);
log4c_category_vlog(__log4c_category__,LOG4C_PRIORITY_CRIT,fmt,argptr);
va_end(argptr);
}
}
void tsc_alert(const char* fmt,...)
{
if(tsc_log_level >= TSC_LOG_ALERT)
{
va_list argptr;
va_start(argptr,fmt);
log4c_category_vlog(__log4c_category__,LOG4C_PRIORITY_ALERT,fmt,argptr);
va_end(argptr);
}
}
void tsc_emerg(const char* fmt,...)
{
if(tsc_log_level >= TSC_LOG_EMERG)
{
va_list argptr;
va_start(argptr,fmt);
log4c_category_vlog(__log4c_category__,LOG4C_PRIORITY_FATAL,fmt,argptr);
va_end(argptr);
}
}
最后给一个测试用例:
main.c
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include "tsc_hal_log.h"
int main()
{
pthread_t thread1,thread2;
printf("%f ",3.14159);
tsc_log_init(10240000, 1024000, "../../log/", "log.txt");
tsc_warn("this is a warn string %d", 234);
tsc_error("this is an error string %c", 'k');
tsc_crit("this is a crit string %s", "zhangcf");
tsc_alert("this is a alert string %f",3.145);
tsc_emerg("this is a emerg string %ld", 123456789);
tsc_debug("this is a debug string");
tsc_info("this is a info string");
tsc_notice("this is a notice string");
tsc_log_fini();
return 0;
}