⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 log.c

📁 支持多进程环境
💻 C
字号:
#include <assert.h>#include <sys/types.h>#include <stdlib.h>#include <string.h>#include <stdarg.h>#include <errno.h>#include <fcntl.h>#include <sys/stat.h>#include <sys/mman.h>#include <unistd.h>#include <sys/time.h>#include <time.h>#include <stdio.h>#include <pthread.h>//#include "benchapi.h"#include "log.h"#define MAX_LOG_CNT	1000enum {	false	= 0,	true	= 1};static int has_init = 0;static int log_level;static u_int log_size;static char log_pre[32] = {0};static char log_dir[256] = {0};static struct fds_t {	int seq;	int opfd;	u_short day;} fds_info[APP_TRACE + 1];static char* log_buffer = MAP_FAILED;static int is_need_sync = 0;pthread_mutex_t mutex;static inline void log_file_name(int lvl, int seq, char* file_name, time_t now){	struct tm tm;	assert (lvl >= APP_EMERG && lvl <= APP_TRACE);	localtime_r(&now, &tm);	sprintf (file_name, "%s/%s%s%04d%02d%02d%03d", log_dir, log_pre, 					((char*[]){						"emerg", "alert", "crit",						"error", "warn", "notice",						"info", "debug", "trace"					})[lvl],					tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, seq);}static int request_log_seq (int lvl){	char file_name[FILENAME_MAX];	int seq;	time_t now = time (NULL);	struct stat buf;	/*	 * find last log and tag with seq	 */	for (seq = 0; seq < MAX_LOG_CNT; seq ++) {		log_file_name (lvl, seq, file_name, now);		if (access (file_name, F_OK)) {			if (seq == 0)				return 0;			else				break;		}	}	if (seq == MAX_LOG_CNT) {		fprintf (stderr, "too many log files\n");		return -1;	}	log_file_name (lvl, --seq, file_name, now);	if (stat (file_name, &buf)) {		 fprintf (stderr, "stat %s error, %m\n", file_name);		 return -1;	}		return seq == 0 ? seq : seq - 1;}static int open_fd(int lvl, time_t now){	char file_name[FILENAME_MAX];	struct tm *tm;	int val;	log_file_name (lvl, fds_info[lvl].seq, file_name, now);	fds_info[lvl].opfd = open (file_name, O_WRONLY|O_CREAT|O_APPEND, 0644);	if (fds_info[lvl].opfd > 0) {		tm = localtime (&now);		fds_info[lvl].day = tm->tm_yday;				val = fcntl(fds_info[lvl].opfd, F_GETFD, 0);		val |= FD_CLOEXEC;		fcntl(fds_info[lvl].opfd, F_SETFD, val);	}	return fds_info[lvl].opfd;}static int shift_fd (int lvl, time_t now){	off_t length; 	struct tm *tm;		if (fds_info[lvl].opfd < 0 && (open_fd (lvl, now) < 0)) 		return -1;	length = lseek (fds_info[lvl].opfd, 0, SEEK_END);	tm = localtime (&now);	if (length < log_size && fds_info[lvl].day == tm->tm_yday)		return 0;	close (fds_info[lvl].opfd);	if ( fds_info[lvl].day != tm->tm_yday)		fds_info[lvl].seq = 0;	else		fds_info[lvl].seq ++;	return open_fd (lvl, now);}void boot_log (int OK, int dummy, const char* fmt, ...){#define SCREEN_COLS	80#define BOOT_OK		"\e[1m\e[32m[ ok ]\e[m"#define BOOT_FAIL	"\e[1m\e[31m[ failed ]\e[m"	int end, i, pos;	va_list ap;	if (log_buffer == MAP_FAILED) {		log_buffer = mmap (0, 4096, PROT_WRITE | PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);		if (log_buffer == MAP_FAILED) {			fprintf (stderr, "mmap log buffer failed, %m\n");			exit (-1);		}	}	va_start(ap, fmt);	end = vsprintf (log_buffer, fmt, ap);	va_end (ap);	pos = SCREEN_COLS - 10 - (end - dummy) % SCREEN_COLS;	for (i = 0; i < pos; i++)		log_buffer[end + i] = ' ';	 log_buffer[end + i] = '\0';	strcat (log_buffer, OK == 0 ? BOOT_OK : BOOT_FAIL);	printf ("\r%s\n", log_buffer);		if (OK != 0) 		exit (OK); }void write_log (int lvl, const char* fmt, ...){	struct tm tm;	struct timezone tz;	struct timeval tv;	int pos, end;	va_list ap;	time_t now;	//int i = 0;	char log_buffer_local[4096] = {0};		if (!has_init) {		va_start(ap, fmt);		switch (lvl) {			case APP_EMERG:			case APP_CRIT:			case APP_ALERT:			case APP_ERROR:				vfprintf (stderr, fmt, ap);				break;			default:				vfprintf (stdout, fmt, ap);				break;		}		va_end(ap);		return;	}	if (lvl > log_level)		return ;		gettimeofday(&tv, &tz);	now = tv.tv_sec; 		if  (shift_fd (lvl, now) < 0)		return ;		localtime_r(&now, &tm);#if TEST//	printf("Before write buffer=\n");	for(i = 0; i< 100; i++)	{//		printf("%c ",log_buffer[i]);	}//	printf("end\n");#endif	if(true == is_need_sync)	{		pthread_mutex_lock(&mutex);	}	if (lvl == APP_INFO || lvl == APP_NOTICE || lvl == APP_WARNING)		pos = sprintf (log_buffer_local, "[%02d:%02d:%02d.%06u]", 			tm.tm_hour, tm.tm_min, tm.tm_sec, (unsigned int)tv.tv_usec);	else		pos = sprintf (log_buffer_local, "[%02d:%02d:%02d.%06u][%05d]", 			tm.tm_hour, tm.tm_min, tm.tm_sec, (unsigned int)tv.tv_usec, getpid());		#if TEST//	printf("After write buffer=\n");	for(i = 0; i< 100; i++)	{//		printf("%c ",log_buffer[i]);	}//	printf("end\n");	//usleep(10);//	printf("After sleep buffer=\n");	for(i = 0; i< 100; i++)	{//		printf("%c ",log_buffer[i]);	}//	printf("end\n");#endif	va_start(ap, fmt);	end = vsprintf (log_buffer_local + pos, fmt, ap);	va_end(ap);	write (fds_info[lvl].opfd, log_buffer_local, end + pos);	if(true == is_need_sync)	{		pthread_mutex_unlock(&mutex);	}}int log_init (const char* dir, int lvl, u_int size, const char* pre_name, int need_sync){	int i, ret_code = -1;		is_need_sync = need_sync;	if (lvl < 0 || lvl > APP_TRACE) {		fprintf (stderr, "init log error, invalid log level=%d\n", lvl);		goto exit_entry;	}	/*	 * log file is no larger than 2GB	 */	if (size > 1<<31) {		fprintf (stderr, "init log error, invalid log size=%d\n", size);		goto exit_entry;	}	if (access (dir, W_OK)) {		fprintf (stderr, "access log dir %s error, %m\n", dir);		goto exit_entry;	}	if (log_buffer == MAP_FAILED) {		log_buffer = mmap (0, 4096, PROT_WRITE | PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);		if (log_buffer == MAP_FAILED) {			fprintf (stderr, "mmap log buffer failed, %m\n");			goto exit_entry;		}	}	strncpy (log_dir, dir, sizeof (log_dir) - 1);	if (pre_name != NULL)		strncpy (log_pre, pre_name, sizeof (log_pre) - 1);	log_size = size;	log_level = lvl;	for (i = APP_EMERG; i <= APP_TRACE; i++) {		fds_info[i].opfd = -1;		fds_info[i].seq = request_log_seq (i);		if (fds_info[i].seq  < 0)			goto exit_entry;	}		has_init = 1;	ret_code = 0;exit_entry:	BOOT_LOG (ret_code, "set log dir %s, per file size %d MB", dir, size/1024/1024);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -