C# · 12月 20, 2021

C/C++格式化日志库的实现

头文件如下:

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

/* 跨平台日志函数,Linux下与windows下亲测有效 */

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

#ifndef _LOG_FORMAT_H_

#define _LOG_FORMAT_H_

// 日志等级

enum LogLevel { _LOG_TRACE,_LOG_INFO,_LOG_WARN,_LOG_ERROR,_LOG_FATAL };

void LogFormat(const char *pszFileName,const int nLine,LogLevel Level,const char *Format,…);

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

/* 日志函数调用方法 _LOG(_LOG_FATAL,”%s”,”sss”); */

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

#ifndef _LOG

#define _LOG(Level,Format,…) LogFormat(__FILE__,__LINE__,Level,##__VA_ARGS__)

#endif

#endif // _LOG_FORMAT_H_

源文件如下:

#include

#include

#include

#include

#if defined __GNUC__ || defined LINUX

#include

#define MY_VA_LIST _G_va_list

#else

#include

#define MY_VA_LIST va_list

#endif

#include “LogFormat.h”

/*

*最终生成的日志字符串最大长度,要特别注意

*超过此长度程序会崩溃,用户可以自定义长度

*/

#define LOG_MAX 1024

/*

*时间长度,不需要修改

*/

#define FORMAT_TIME_SIZE 24

/*

*日志等级字符串,与头文件中定义的枚举必须一致

*/

static std::string g_LogLevel[] = { “TRACE”,”INFO”,”WARN”,”ERROR”,”FATAL” };

/*

*内存申请函数,用户可以自定义

*/

static char *NewBuf(const uint32_t unBufSize)

{

return new char[unBufSize];

}

/*

*内存释放函数,必须与NewBuf对应

*/

static void DeleteBuf(char ** pszBuf)

{

if (NULL != *pszBuf)

{

delete[] *pszBuf;

*pszBuf = NULL;

}

*pszBuf = NULL;

}

/*

*获取当前时间字符串函数

*2018-08-08 08:08:08.888

*/

static char* GetTime()

{

char *pszFormatTime = NewBuf(FORMAT_TIME_SIZE);

#if defined __GNUC__ || defined LINUX

struct timeval tv;

struct timezone tz;

gettimeofday(&tv,&tz);

struct tm *current_time = localtime(&tv.tv_sec);

sprintf(pszFormatTime,

“%04d-%02d-%02d %02d:%02d:%02d.%03d”,

current_time->tm_year + 1900,

current_time->tm_mon + 1,

current_time->tm_mday,

current_time->tm_hour,

current_time->tm_min,

current_time->tm_sec,

tv.tv_usec / 1000);

#else

SYstemTIME sys_time;

GetLocalTime(&sys_time);

#if _MSC_VER

sprintf_s(pszFormatTime,

FORMAT_TIME_SIZE,

sys_time.wYear,

sys_time.wMonth,

sys_time.wDay,

sys_time.wHour,

sys_time.wMinute,

sys_time.wSecond,

sys_time.wMilliseconds);

#else

sprintf(pszFormatTime,

sys_time.wMilliseconds);

#endif

#endif

return pszFormatTime;

}

void LogFormat(const char *pszFileName,…)

{

int ret = 0;

char *pszDescribeInfo = NewBuf(LOG_MAX);

MY_VA_LIST ap;

va_start(ap,Format);

#if defined __GNUC__ || defined LINUX

ret = vsnprintf(pszDescribeInfo,

LOG_MAX,

Format,

ap);

#else

#if _MSC_VER

ret = _vsnprintf_s(pszDescribeInfo,

_TRUNCATE,

ap);

#else

ret = _vsnprintf(pszDescribeInfo,

ap);

#endif

#endif

va_end(ap);

if ((LOG_MAX ret))

{

DeleteBuf(&pszDescribeInfo);

return;

}

// 组装日志,[时间][等级][文件名(行数)][自定义字符串]

char *pszLog = NewBuf(LOG_MAX);

char *pszTime = GetTime();

#if defined __GNUC__ || defined LINUX

ret = sprintf(pszLog,

“[%s][%s][%s(%d)][%s]”,

pszTime,

g_LogLevel[Level].c_str(),

pszFileName,

nLine,

pszDescribeInfo);

#else

#if _MSC_VER

ret = sprintf_s(pszLog,

pszDescribeInfo);

#else

ret = sprintf(pszLog,

pszDescribeInfo);

#endif

#endif

// 日志默认输出到控制台,用户可以自行修改

printf(“%sn”,pszLog);

DeleteBuf(&pszDescribeInfo);

DeleteBuf(&pszLog);

DeleteBuf(&pszTime);

}