0 前言
自定义的日志功能, 之前已经介绍过使用log4qt和qInstallMessageHandler实现日志输出
这个是用c实现的日志功能
1 实现效果
输出格式 [时间] [日志类型] [错误返回值] 日志内容
定位文件和行号
2 目录结构
3 源码
main.cpp
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "log.h"
int main(void)
{
//C语言自带宏
// __FILE__: 左右两边都有2个下划线,当前__FILE__所在的文件, %s
// __LINE__: 当前__LINE__所在的行, %d
printf("file = %s\nline = %d\n", __FILE__, __LINE__);
int a = 10;
LOG(__FILE__, __LINE__, 0, -1, "nolog = %d\n", a);
LOG(__FILE__, __LINE__, 1, -1, "debug = %d\n", a);
LOG(__FILE__, __LINE__, 2, -1, "info = %d\n", a);
LOG(__FILE__, __LINE__, 3, -1, "warn = %d\n", a);
LOG(__FILE__, __LINE__, 4, -1, "error = %d\n", a);
printf("\n");
system("pause");
return 0;
}
Log.h
#ifndef _LOG_H_
#define _LOG_H_
#define FILENAME "./debug.log"
/*
#define IC_NO_LOG_LEVEL 0
#define IC_DEBUG_LEVEL 1
#define IC_INFO_LEVEL 2
#define IC_WARNING_LEVEL 3
#define IC_ERROR_LEVEL 4;
*/
/************************************************************************/
/*
const char *file:文件名称,写:__FILE__
int line:文件行号,写:__LINE__
int level:错误级别
0 -- 没有日志
1 -- debug级别
2 -- info级别
3 -- warning级别
4 -- err级别
int status:错误码
const char *fmt:可变参数
*/
/************************************************************************/
//实际使用的Level
extern int LogLevel[5];
void LOG(const char *file, int line, int level, int status, const char *fmt, ...);
#endif
Log.c
#define _CRT_SECURE_NO_WARNINGS
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdarg.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "Log.h"
#define MAX_STRING_LEN 10240
//Level类别
#define NO_LOG_LEVEL 0
#define DEBUG_LEVEL 1
#define INFO_LEVEL 2
#define WARNING_LEVEL 3
#define ERROR_LEVEL 4
int LogLevel[5] = {NO_LOG_LEVEL, DEBUG_LEVEL, INFO_LEVEL, WARNING_LEVEL, ERROR_LEVEL};
//Level的名称
char ICLevelName[5][10] = {"NOLOG", "DEBUG", "INFO", "WARNING", "ERROR"};
static int Error_GetCurTime(char* strTime)
{
struct tm* tmTime = NULL;
size_t timeLen = 0;
time_t tTime = 0;
tTime = time(NULL);
tmTime = localtime(&tTime);
//timeLen = strftime(strTime, 33, "%Y(Y)%m(M)%d(D)%H(H)%M(M)%S(S)", tmTime);
timeLen = strftime(strTime, 33, "%Y.%m.%d %H:%M:%S", tmTime);
return timeLen;
}
static int Error_OpenFile(int* pf)
{
char fileName[1024];
memset(fileName, 0, sizeof(fileName));
#ifdef WIN32
sprintf(fileName, "%s",FILENAME);
#else
sprintf(fileName, "%s", FILENAME);
#endif
*pf = open(fileName, O_WRONLY|O_CREAT|O_APPEND, 0666);
if(*pf < 0)
{
return -1;
}
return 0;
}
static void Error_Core(const char *file, int line, int level, int status, const char *fmt, va_list args)
{
char str[MAX_STRING_LEN];
int strLen = 0;
char tmpStr[64];
int tmpStrLen = 0;
int pf = 0;
//初始化
memset(str, 0, MAX_STRING_LEN);
memset(tmpStr, 0, 64);
//加入LOG时间
tmpStrLen = Error_GetCurTime(tmpStr);
tmpStrLen = sprintf(str, "[%s] ", tmpStr);
strLen = tmpStrLen;
//加入LOG等级
tmpStrLen = sprintf(str+strLen, "[%s] ", ICLevelName[level]);
strLen += tmpStrLen;
//加入LOG状态
if (status != 0)
{
tmpStrLen = sprintf(str+strLen, "[ERRNO is %d] ", status);
}
else
{
tmpStrLen = sprintf(str+strLen, "[SUCCESS] ");
}
strLen += tmpStrLen;
//加入LOG信息
tmpStrLen = vsprintf(str+strLen, fmt, args);
strLen += tmpStrLen;
//加入LOG发生文件
tmpStrLen = sprintf(str+strLen, " [%s]", file);
strLen += tmpStrLen;
//加入LOG发生行数
tmpStrLen = sprintf(str+strLen, " [%d]\n", line);
strLen += tmpStrLen;
//打开LOG文件
if(Error_OpenFile(&pf))
{
return ;
}
//写入LOG文件
write(pf, str, strLen);
//IC_Log_Error_WriteFile(str);
//关闭文件
close(pf);
return ;
}
void LOG(const char *file, int line, int level, int status, const char *fmt, ...)
{
va_list args;
//判断是否需要写LOG
// if(level!=IC_DEBUG_LEVEL && level!=IC_INFO_LEVEL && level!=IC_WARNING_LEVEL && level!=IC_ERROR_LEVEL)
if(level == NO_LOG_LEVEL)
{
return ;
}
//调用核心的写LOG函数
va_start(args, fmt);
Error_Core(file, line, level, status, fmt, args);
va_end(args);
return ;
}