您的位置:首页 > 编程语言 > C语言/C++

C语言多线程下不同等级日志的实现

2015-06-07 15:58 477 查看
/***********************************************************************

模块名称:C语言多级别日志模块的实现

模块功能:多线程环境下实现多级别日志的记录

模块描述:通过日志产生的时间,将之分别记录到通过时间命名的文件夹下,并可设定日志的输出级别

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

//sys_log.h

#ifndef SYS_LOG_H
#define SYS_LOG_H

#include <stdio.h>

#ifdef __cplusplus
extern
"C" {
#endif
#define TRUE  1
#define FALSE 0
#define IN
#define OUT
#define LOG_PATH "sys_log"

typedef enum {
DEBUG,
INFO,
WARN,
ERROR,
OFF
}LOG_LEVEL;

void  set_log_level(
IN LOG_LEVEL level
);

char* log_level_2_str(
IN LOG_LEVEL level
);

LOG_LEVEL log_str_2_level(
IN const char* level
);

void write_log(
IN LOG_LEVEL level, // 日志级别
IN const char* file,  //打印日志所在的文件
IN const char* function,//打印日志的函数名
IN int line, 		//打印日志的行号
IN const char* format,//日志格式
...
);

void write_log_2_file(
IN const char* file_name,//需要保存的日志文件名
IN LOG_LEVEL level, // 日志级别
IN const char* file,  //打印日志所在的文件
IN const char* function,//打印日志的函数名
IN int   line, //打印日志的行号
IN const char* msg
);

//设置日志路径
void set_log_path(IN const char* path);

//日志到标准输出
void log_terminal();

//日志关闭到标准输出
void log_shutdown_terminal();

//日志关闭写入到文件
void log_shutdown_file();

void log_to_file();

//日志管理
#define LOG_DEBUG(format, ...) write_log(DEBUG, __FILE__, __FUNCTION__, __LINE__, format, ##__VA_ARGS__)

#define LOG_ERROR(format, ...) write_log(ERROR, __FILE__, __FUNCTION__, __LINE__, format, ##__VA_ARGS__)

#define LOG_INFO(format, ...)  write_log( INFO, __FILE__, __FUNCTION__, __LINE__, format, ##__VA_ARGS__)

#define LOG_WARN(format, ...)  write_log(WARN, __FILE__, __FUNCTION__, __LINE__, format, ##__VA_ARGS__)

#ifdef __cplusplus
}
#endif

#endif


//sys_thread.c

#include <string.h>

typedef struct tagTHREAD_INFO{
char      name[64];
pthread_t tid;
}THREAD_INFO;

static THREAD_INFO g_thread_info[1024];
static int         g_thread_num = 0;

void register_thread_name(
IN  pthread_t    tid,
IN  const char*  name
)
{
memset((void*)&g_thread_info[g_thread_num], 0, sizeof(THREAD_INFO));
g_thread_info[g_thread_num].tid = tid;
memcpy((void*)g_thread_info[g_thread_num].name, (void*)name, strlen(name));
g_thread_num++;
}

char* get_thread_name()
{
int = 0;
pthread_t tid = pthread_self();
for (; i<g_thread_num; i++)
{
if (tid == g_thread_info[i].tid)
{
return g_thread_info[i].name;
}
}

return NULL;
}

//sys_log.c

//sys_log.c
#include <stdarg.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>

#include "sys_log.h"
#include "sys_thread.h"

char g_log_root[64] = {0} ;
char g_start_time[64] = {0};

//默认的日志级别
static LOG_LEVEL g_log_level = DEBUG;

static int g_log_terminal = TRUE;

static int g_log_to_file = TRUE;

void log_terminal()
{
g_log_terminal = TRUE;
}

void log_shutdown_terminal()
{
g_log_terminal = FALSE;
}

void log_shutdown_file()
{
g_log_to_file = FALSE;
}

void log_to_file()
{
g_log_to_file = TRUE;
}

void set_log_path(IN const char* path)
{
if (path)
{
memcpy(g_log_root, path, strlen(path));
}
}

void set_log_level(
IN LOG_LEVEL level
)
{
g_log_level = level;
}

LOG_LEVEL log_str_2_level(
IN const char* level
)
{
if (!level)
{
return DEBUG;
}

if (strcmp("DEBUG", level) == 0)
{
return DEBUG;
}

if (strcmp("INFO", level) == 0)
{
return INFO;
}

if (strcmp("WARN", level) == 0)
{
return WARN;
}

if (strcmp("ERROR", level) == 0)
{
return ERROR;
}

if (strcmp("OFF", level) == 0)
{
return OFF;
}

return DEBUG;
}

char* log_level_2_str(
IN LOG_LEVEL level
)
{
switch (level)
{
case DEBUG:
return (char*)"DEBUG";
case INFO:
return (char*)"INFO";
case WARN:
return (char*)"WARN";
case ERROR:
return (char*)"ERROR";
case OFF:
return (char*)"OFF";
default:
return (char*)"UNKNOW";
}

return (char*)"UNKNOW";
}

void write_log(
IN LOG_LEVEL level, // 日志级别
IN const char* file, //打印日志所在的文件
IN const char* function,//打印日志的函数名
IN int line, //打印日志的行号
IN const char* format,//日志格式
IN ...
)
{
if (level < g_log_level)
{
return;
}

if (!strlen(g_log_root))
{
//生成日志文件的名字
memcpy(g_log_root, LOG_PATH, strlen(LOG_PATH));
//assert(ret == 0);
}
mkdir(g_log_root, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
time_t now = time(NULL);
char timestamp[128] = {0};
struct tm date;
struct tm *ptr = localtime_r(&now, &date);
strftime(timestamp, sizeof(timestamp), "%Y-%m-%d", ptr);
char forder[160] = {0};
sprintf(forder, "%s/%s", g_log_root, timestamp);
mkdir(forder, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);

//开始运行时间再创建一个目录
if (strlen(g_start_time) == 0)
{
memset(g_start_time, 0, sizeof(g_start_time));
strftime(g_start_time, sizeof(timestamp), "%H_%M_%S", ptr);
}

memset(forder, 0, sizeof(forder));
sprintf(forder, "%s/%s/%s", g_log_root, timestamp, g_start_time);
mkdir(forder, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
char threadId[256] = {0};
char* threadName = get_thread_name();
if (!threadName)
{
sprintf(threadId, "%s/thread.%lld.log", forder, pthread_self());
} else {
sprintf(threadId, "%s/thread.%s.log", forder, threadName);
}
va_list vap;
va_start(vap , format);
char msg[2048] = {0};
vsnprintf(msg, sizeof(msg), format, vap);
write_log_2_file(threadId, level, file, function, line, msg);
va_end(vap);

}

void write_log_2_file(
IN const char* file_name,//需要保存的日志文件名
IN LOG_LEVEL level, // 日志级别
IN const char* file, //打印日志所在的文件
IN const char* function,//打印日志的函数名
IN int line, //打印日志的行号
IN const char* msg
)
{

FILE *fp = NULL;
fp = fopen(file_name, "a+");

if (!fp)
{
return;
}

//assert(fp);

char log_info[4092] = {0};

//获取当前系统时间
time_t now = time(NULL);;
struct tm date;
char timestamp[80] = {0};
struct tm *ptr = localtime_r(&now, &date);
strftime(timestamp, 100, "%B %d %Y %T", ptr);

sprintf(log_info, "[%s|%s|%s:%d|%s]%s\n", timestamp,
log_level_2_str(level), function, line, get_thread_name(), msg);

if (g_log_to_file)
{
fwrite(log_info, sizeof(char), strlen(log_info), fp);
}

fclose(fp);
if (g_log_terminal) {
fprintf(stdout, log_info);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息