您的位置:首页 > 运维架构 > Linux

一个同步日志系统的简单实现 log for c (linux 平台)

2013-12-03 21:18 393 查看
在一个项目中需要使用日志记录,网上也有很多开源代码,自己也尝试着写了一个!异步日志系统正在进行中。

//mylog.h  头文件
#ifndef _MYLOG_HEADER_
#define  _MYLOG_HEADER_

#ifdef __cpluscplus
extern "C"{
#endif

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <sys/epoll.h>
#include <sys/eventfd.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <time.h>
#include <error.h>

#define LOG_MAX_FILE_NAME	(64)
#define LOG_MAX_OUTPUT_NAME (128)

#define LOG_TIME_STR_LEN (21)

#define MAX_FILE_COUNT (50)

#define MAX_FILE_SIZE (1024*1024*3)

/****************
  每一个文件对于一个这样的结构体
  ,不管是多线程写还是单线程 
  都是对应一个描述文件的结构体
 ****************************/

typedef struct _log_file_t_
{
	FILE *fp;  //文件指针
	unsigned char filename[LOG_MAX_FILE_NAME];//输入文件的名字
	unsigned char output_filename[LOG_MAX_OUTPUT_NAME];//输出文件的名字
	unsigned int  filesize;// 当前文件的大小
	unsigned int  active_count;//写文件的线程数
}log_file_t;

typedef struct _log_t
{
	pthread_key_t key;
	pthread_mutex_t mutex;
	unsigned int roll_size;
	unsigned int max_filesize;
	log_file_t *file_count[MAX_FILE_COUNT];
	unsigned char last_time_str[LOG_TIME_STR_LEN+1];
	unsigned int file_index;
}f_log;

char* _log_create_filename(char* filename,char* output_filename);

#ifdef __cpluscplus
}
#endif

#endif


函数实现:

#include "mylog.h"

static f_log* g_log = NULL;
static pthread_once_t init_create = PTHREAD_ONCE_INIT;

/*********************

  内部函数实现

 ********************/
// 全局变量 初始化
static void _log_init()
{
	int i;
	f_log *temp_glo=NULL;
	temp_glo = (f_log*)malloc(sizeof(f_log));
	if(temp_glo == NULL)
	{
		printf("Can not malloc f_log!!!\r\n");
		return ;

	}
	pthread_mutex_init(&temp_glo->mutex,NULL);

	temp_glo->max_filesize = MAX_FILE_SIZE; // 20MB
	temp_glo->file_index = 0;
	for(i=0;i<MAX_FILE_COUNT;i++)
	{
		temp_glo->file_count[i] == NULL;
	}
	g_log=temp_glo;
}
static inline int _lopen(const char* filename)
{
	return open(filename,O_CREAT | O_WRONLY | O_APPEND,644);
}

static inline FILE* _log_open(const char* filename)
{
	int fd= _lopen(filename);
	if(fd<0)
	{
		printf("Can not open file !\r\n");
		return NULL;
	}
	FILE* f = fdopen(fd,"a");
	if(f== NULL)
	{
		printf("Can open not \r\n");
		return NULL;

	}
	return f;
}

// 写封装
static int _log_write_unlocked(log_file_t *f,char* log,int len)
{
	int remain_len,write_len,temp;
	remain_len = len;
	write_len = 0;
	while(remain_len)
	{
		temp=fwrite(log,1,len,f->fp);
		write_len+=temp;
		//		printf("fddfdfdffd\r\n");
		remain_len-=temp;

	}
	return write_len;
}

static void _log_roll_file(log_file_t* f)
{

	fclose(f->fp);
	_log_create_filename(f->filename,f->output_filename);
	f->fp = _log_open(f->output_filename);
	f->filesize = 0;
//	snprintf(f->filename,LOG_MAX_FILE_NAME,"%s",filename);

}

// 写日志
static int _log_write(log_file_t *f,char* log,int len)
{
	int write_len=0;
	if(!f || !log )
	{
		return 0;
	}
	write_len=_log_write_unlocked(f,log,len);
	if(write_len < len)
	{
		printf("Can not write log to f!\r\n");
		return 0;
	}
	fflush(f->fp);
	f->filesize +=write_len;
	if(f->filesize > g_log->max_filesize)
	{
		
		_log_roll_file(f);

	}

	return write_len;
}

char* _log_create_filename(char* filename,char* output_filename)
{
	char now_time[22];
	time_t tm_time = time(NULL);
	struct tm now;
	gmtime_r(&tm_time,&now);
	snprintf(now_time,22,"%04d_%02d_%02d_%02d_%02d_%02d",(now.tm_year+1900),now.tm_mon+1,now.tm_mday,now.tm_hour,now.tm_min,now.tm_sec);
	snprintf(output_filename,LOG_MAX_OUTPUT_NAME,"%s_%s.txt",filename,now_time);
	return output_filename;

}

static void _log_get_time(time_t tm_time,char* time_str)
{
	struct tm now;
	gmtime_r(&tm_time,&now);
	snprintf(time_str,LOG_TIME_STR_LEN+1,"[%04d_%02d_%02d %02d:%02d:%02d]",(now.tm_year+1900),now.tm_mon+1,now.tm_mday,now.tm_hour,now.tm_min,now.tm_sec);

}

static int _log_get_file_sig(char* file_sig,int file_sig_len,char* output_file_sig)
{
	if(!file_sig)
	{
		return 0;
	}
	snprintf(output_file_sig,file_sig_len+3,"[%s]",file_sig);
	//	printf("output file sig is %s\r\n",output_file_sig);
	return 1;

}
static inline int _log_get_sync_head(char* buf,char* file_sig,int file_sig_len)
{
	time_t tm_check = time(NULL);
	char sig_buf[file_sig_len+2];
	if( !buf)
	{
		return 0;
	}
	pthread_mutex_lock(&g_log->mutex);
	_log_get_time(tm_check,g_log->last_time_str);
	_log_get_file_sig(file_sig,file_sig_len,sig_buf);
	pthread_mutex_unlock(&g_log->mutex);
	strncpy(buf,g_log->last_time_str,LOG_TIME_STR_LEN);
	if(!file_sig) 
	{
		file_sig_len = 0;
	}
	else
	{
		strncpy(buf+LOG_TIME_STR_LEN,sig_buf,file_sig_len+2);
	}

	return LOG_TIME_STR_LEN+file_sig_len+2;

}

// 写日志 在封装 是否达到文件的最大值
static int _log_sync_write(log_file_t *f,char* file_sig,int file_sig_len,char* log,int len)
{
	int write_len,head_len;
	write_len =0;
	char buf[LOG_TIME_STR_LEN+file_sig_len+2+1];
	head_len = _log_get_sync_head(buf,file_sig,file_sig_len);
	pthread_mutex_lock(&g_log->mutex);

	write_len += _log_write(f,buf,head_len);

	//	write_len += _log_write(f,file_sig,file_sig_len);
	write_len += _log_write(f,log,len);
	write_len += _log_write(f,"\n",1);
	//	printf("write_len is %d\r\n",write_len);
	pthread_mutex_unlock(&g_log->mutex);
	return 1;

}

void  find_file(f_log *g_log,char* filename,log_file_t** created_file)
{
	int i;
	*created_file == NULL;
	for(i=0;i<g_log->file_index;i++)
	{
		if(!strcmp(filename,g_log->file_count[i]->filename))
		{
			*created_file=g_log->file_count[i];		

		}
	}
}

/**************************

  外部函数 接口

 **************************/
// 初始化描述文件的结构体
log_file_t* log_create(char* filename)
{
	pthread_once(&init_create,_log_init);
	log_file_t *f=NULL;

	pthread_mutex_lock(&g_log->mutex);
	{
		find_file(g_log,filename,&f);
		if(f)
		{
			f->active_count++;
			pthread_mutex_unlock(&g_log->mutex);
			return f;

		}
		f = malloc(sizeof(log_file_t));
		if(!f)
		{
			printf("Can not malloc f!\r\n");
			pthread_mutex_unlock(&g_log->mutex);
			return NULL;

		}
		_log_create_filename(filename,f->output_filename);
		f->fp = _log_open(f->output_filename);
		f->filesize = 0;
		snprintf(f->filename,LOG_MAX_FILE_NAME,"%s",filename);
		g_log->file_count[g_log->file_index]=f;
		g_log->file_index++;
		f->active_count = 1;

	}
	pthread_mutex_unlock(&g_log->mutex);

	return f;
}
 

// 阻塞写 & 非阻塞写
int log_file_write(log_file_t* f,char* file_sig,int file_sig_len,char* log,int len)
{

	if(!f || !log)
	{

		printf("F is null!\r\n");	
		return 0;
	}

	_log_sync_write(f,file_sig,file_sig_len,log,len);
//	_log_async_write(f,file_sig,file_sig_len,log,len);
	
	return 0;
}
自己的测试 程序:

#include "mylog.h"

typedef struct _log_info_
{
	unsigned char name[16];
	unsigned char file_sig[16];
	unsigned char log[256];
	unsigned int  log_len;
	unsigned int  file_sig_len;
	unsigned int i;
}log_info;

void *thread_func(void* argc)
{
	log_info *file_info=(log_info*)argc;
	log_file_t * f=NULL;
	f=log_create(file_info->name);
	//	log_set_mode(1);
	int i;
	for(i=0;i<500000;i++)
		log_file_write(f,file_info->file_sig,file_info->file_sig_len,file_info->log,file_info->log_len);

}

int main()
{

	struct timeval start,end;
	log_info log_test;
	pthread_t pid[100];
	memset(&log_test,0x00,sizeof(log_test));
	strcpy(log_test.name,"aest");
	strcpy(log_test.file_sig,"wang");
	strcpy(log_test.log,"fdsajlkfjdsjlkfjdlsajfdlskfjlakdjflkdjsalfkjdslkfjdlakjflkdsjfjfdklstest");
	//	strcpy(log_test.log,"fdsajltest");
	log_test.log_len=strlen(log_test.log);
	log_test.file_sig_len = strlen(log_test.file_sig);
	log_file_t *f=NULL;
	int i,ret;
	f=log_create(log_test.name);
	memset(&start,0x00,sizeof(start));
	memset(&end,0x00,sizeof(end));

#if 1

	gettimeofday(&start,NULL);
	for(i=0;i<900000;i++)
	{
		if(i%1000 == 0)
		{
			printf("a\r\n");
	//		f=log_create(log_test.name);
			}
		log_file_write(f,log_test.file_sig,log_test.file_sig_len,log_test.log,log_test.log_len);

	}
	gettimeofday(&end,NULL);
	printf("time is %d\r\n",(end.tv_sec-start.tv_sec)*1000000+(end.tv_usec-start.tv_usec));

#endif 
#if 0 

	gettimeofday(&start,NULL);
	for(i=0;i<3;i++)
	{
		//		log_test.i=i;
		//	printf("i is %d\n",i);
		ret=pthread_create(&pid[i],NULL,thread_func,(void*)&log_test);
		pthread_join(pid[i],NULL);
		if(ret!=0)
			printf("can not create!\n");
		usleep(100);
	}
	sleep(10);
	gettimeofday(&end,NULL);
	printf("time is %d\r\n",(end.tv_sec-start.tv_sec)*1000000+(end.tv_usec-start.tv_usec));

#endif

	return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: