C语言多线程下不同等级日志的实现
2015-06-07 15:58
477 查看
/***********************************************************************
模块名称:C语言多级别日志模块的实现
模块功能:多线程环境下实现多级别日志的记录
模块描述:通过日志产生的时间,将之分别记录到通过时间命名的文件夹下,并可设定日志的输出级别
/***********************************************************************
//sys_log.h
//sys_thread.c
//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);
}
}
模块名称: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);
}
}
相关文章推荐
- Lua和C语言的交互详解
- 关于C语言中参数的传值问题
- 深入C++中API的问题详解
- 基于C语言string函数的详解
- C语言内存对齐实例详解
- c语言实现的带通配符匹配算法
- C语言实现顺序表基本操作汇总
- 探讨C语言的那些小秘密之断言
- 深入探讨C语言中局部变量与全局变量在内存中的存放位置
- C语言泛型编程实例教程
- C语言中使用lex统计文本文件字符数
- 基于C语言fflush()函数的使用详解
- C语言单链队列的表示与实现实例详解
- 关于C语言除0引发的思考
- 深入分析C中不安全的sprintf与strcpy
- Lua教程(四):在Lua中调用C语言、C++的函数
- C语言求幂计算的高效解法
- C语言实现输入一颗二元查找树并将该树转换为它的镜像
- 12个关于C语言的有趣问答
- 探讨register关键字在c语言和c++中的差异