实例
file.h
#ifndef _FILE_H
#define _FILE_H
#include <stdio.h>
#include <stdlib.h>
#define LOG_LEVEL_FATAL 0
#define LOG_LEVEL_ERROR 1
#define LOG_LEVEL_WARN 2
#define LOG_LEVEL_INFO 3
#define LOG_LEVEL_DEBUG 4
#define LOG_LEVEL_MAX 5
#define self_dbg printf
#define self_err printf
#define self_warn printf
#define self_info printf
typedef enum {
LOG_OFF = 0,
LOG_ON
} LOG_SWITCH;
struct log_config{
unsigned int global_log_level;
unsigned int log_buf_size;
LOG_SWITCH logfile_log_to_file_switch;
char logfile_log_files_dir[256];
unsigned int logfile_nr_rolling_files;
unsigned long long logfile_max_file_size;
unsigned int logfile_flush_to_disk_period;
};
struct log_config* get_log_configs(void);
static int get_exec_name(char *name);
static int log_files_dir_init(char* dir);
LOG_SWITCH get_log_file_switch_status(void);
void output_log_to_file(char *log, unsigned int size);
void log_to_file_init(void);
#endif
file.c
#include <fcntl.h>
#include <pthread.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include "file.h"
static unsigned int timer_counter;
static pthread_mutex_t log_dir_path_mutex;
static unsigned int log_dir_path_change;
static FILE *file_fp = NULL;
static unsigned long long log_file_size;
static struct log_config log_cfgs = {
.global_log_level = LOG_LEVEL_INFO,
.log_buf_size = 0x100000, // 1MBytes
.logfile_log_to_file_switch = LOG_OFF,
.logfile_nr_rolling_files = 8, // default save 8 log files
.logfile_max_file_size = 0xffffff,
.logfile_flush_to_disk_period = 1,
};
static int get_exec_name(char *name)
{
char path[1024]={0};
int ret = readlink("/proc/self/exe",path,sizeof(path)-1);
if(ret == -1)
{
printf("---- get exec name fail!!\n");
return -1;
}
path[ret]= '\0';
char *ptr = strrchr(path,'/');
strcpy(name, ptr+1);
return 0;
}
static void* timer_thread(void *arg)
{
while(1) {
sleep(get_log_configs()->logfile_flush_to_disk_period);
timer_counter++;
}
return NULL;
}
struct log_config* get_log_configs(void)
{
return &log_cfgs;
}
static int log_files_dir_init(char* dir)
{
char cmd[256];
char path_index[256];
char path_log_dir[256];
char process_name[256];
char path_log_file[256];
char path_link_cur_log[256];
FILE *fp;
unsigned int index;
char buf[32];
int n;
get_exec_name(process_name);
sprintf(path_log_dir, "%s/%s", dir, process_name);
if (-1 == access(path_log_dir, 0)) {
/* log dir is not exists, so create it */
sprintf(cmd, "mkdir -p %s", path_log_dir);
system(cmd);
}
sprintf(path_index, "%s/index", path_log_dir);
if (-1 == access(path_index, 0)) {
index = 0;
} else {
fp = fopen(path_index, "r");
if (NULL == fp) {
self_err("open file: %s error:%d\n", path_index, errno);
return -errno;
}
n = fread(buf, 1, sizeof(buf), fp);
self_dbg("read index file: n:%d content:%s\n", n, buf);
if (0 == n)
index = 0;
else {
index = strtoul(buf, NULL, 10);
index++;
}
fclose(fp);
}
fp = fopen(path_index, "w");
if (NULL == fp) {
self_err("open file: %s error:%d\n", path_index, errno);
return -errno;
}
sprintf(buf, "%d", index);
self_dbg("index:%d, write to index file buf:%s\n", index, buf);
fwrite(buf, 1, strlen(buf), fp);
fflush(fp);
fclose(fp);
if (index >= get_log_configs()->logfile_nr_rolling_files) {
sprintf(path_log_file, "%s/%s_%d.log", path_log_dir, process_name,
index - get_log_configs()->logfile_nr_rolling_files);
remove(path_log_file);
}
sprintf(path_log_file, "%s/%s_%d.log", path_log_dir, process_name, index);
file_fp = fopen(path_log_file, "w");
if (NULL == file_fp) {
self_err("open file: %s error:%d\n", path_log_file, errno);
}
log_file_size = 0;
sprintf(path_link_cur_log, "%s/current.log", path_log_dir);
self_dbg("path_log_file: %s path_link_cur_log:%s\n",
path_log_file, path_link_cur_log);
sprintf(cmd, "rm -f %s", path_link_cur_log);
self_dbg("cmd:%s\n", cmd);
system(cmd);
sprintf(cmd, "ln -s %s %s", path_log_file, path_link_cur_log);
self_dbg("cmd:%s\n", cmd);
system(cmd);
return 0;
}
LOG_SWITCH get_log_file_switch_status(void)
{
return get_log_configs()->logfile_log_to_file_switch;
}
void output_log_to_file(char *log, unsigned int size)
{
static unsigned int last_counter = 0;
struct log_config *cfg = get_log_configs();
if (log_dir_path_change) {
pthread_mutex_lock(&log_dir_path_mutex);
log_dir_path_change = 0