271 lines
6.4 KiB
C++
271 lines
6.4 KiB
C++
//logger.cpp
|
||
#include "logger.h"
|
||
#include <time.h>
|
||
#include <stdarg.h>
|
||
#include <direct.h>
|
||
#include <vector>
|
||
|
||
using std::string;
|
||
using std::vector;
|
||
|
||
namespace LOGGER
|
||
{
|
||
CLogger::CLogger(EnumLogLevel nLogLevel, const std::string strLogPath, const std::string strLogName)
|
||
:m_nLogLevel(nLogLevel),
|
||
m_strLogPath(strLogPath),
|
||
m_strLogName(strLogName)
|
||
{
|
||
//初始化
|
||
m_pFileStream = NULL;
|
||
if (m_strLogPath.empty())
|
||
{
|
||
m_strLogPath = GetAppPathA();
|
||
}
|
||
if (m_strLogPath[m_strLogPath.length()-1] != '\\')
|
||
{
|
||
m_strLogPath.append("\\");
|
||
}
|
||
//创建文件夹
|
||
//MakeSureDirectoryPathExists(m_strLogPath.c_str());
|
||
//创建日志文件
|
||
if (m_strLogName.empty())
|
||
{
|
||
time_t curTime;
|
||
time(&curTime);
|
||
tm tm1;
|
||
localtime_s(&tm1, &curTime);
|
||
//日志的名称如:201601012130.log
|
||
m_strLogName = FormatString("%04d%02d%02d_%02d%02d%02d.log", tm1.tm_year + 1900, tm1.tm_mon + 1, tm1.tm_mday, tm1.tm_hour, tm1.tm_min, tm1.tm_sec);
|
||
}
|
||
m_strLogFilePath = m_strLogPath.append(m_strLogName);
|
||
|
||
//以追加的方式打开文件流
|
||
fopen_s(&m_pFileStream, m_strLogFilePath.c_str(), "a+");
|
||
|
||
InitializeCriticalSection(&m_cs);
|
||
}
|
||
|
||
|
||
//析构函数
|
||
CLogger::~CLogger()
|
||
{
|
||
//释放临界区
|
||
DeleteCriticalSection(&m_cs);
|
||
//关闭文件流
|
||
if (m_pFileStream)
|
||
{
|
||
fclose(m_pFileStream);
|
||
m_pFileStream = NULL;
|
||
}
|
||
}
|
||
|
||
//文件全路径得到文件名
|
||
const char *CLogger::path_file(const char *path, char splitter)
|
||
{
|
||
return strrchr(path, splitter) ? strrchr(path, splitter) + 1 : path;
|
||
}
|
||
|
||
//写严重错误信息
|
||
void CLogger::TraceFatal(const char *lpcszFormat, ...)
|
||
{
|
||
//判断当前的写日志级别
|
||
if (EnumLogLevel::LogLevel_Fatal > m_nLogLevel)
|
||
return;
|
||
string strResult;
|
||
if (NULL != lpcszFormat)
|
||
{
|
||
va_list marker = NULL;
|
||
va_start(marker, lpcszFormat); //初始化变量参数
|
||
size_t nLength = _vscprintf(lpcszFormat, marker) + 1; //获取格式化字符串长度
|
||
std::vector<char> vBuffer(nLength, '\0'); //创建用于存储格式化字符串的字符数组
|
||
int nWritten = _vsnprintf_s(&vBuffer[0], vBuffer.size(), nLength, lpcszFormat, marker);
|
||
if (nWritten > 0)
|
||
{
|
||
strResult = &vBuffer[0];
|
||
}
|
||
va_end(marker); //重置变量参数
|
||
}
|
||
if (strResult.empty())
|
||
{
|
||
return;
|
||
}
|
||
string strLog = strFatalPrefix;
|
||
strLog.append(GetTime()).append(strResult);
|
||
|
||
//写日志文件
|
||
Trace(strLog);
|
||
}
|
||
|
||
//写错误信息
|
||
void CLogger::TraceError(const char *lpcszFormat, ...)
|
||
{
|
||
//判断当前的写日志级别
|
||
if (EnumLogLevel::LogLevel_Error > m_nLogLevel)
|
||
return;
|
||
string strResult;
|
||
if (NULL != lpcszFormat)
|
||
{
|
||
va_list marker = NULL;
|
||
va_start(marker, lpcszFormat); //初始化变量参数
|
||
size_t nLength = _vscprintf(lpcszFormat, marker) + 1; //获取格式化字符串长度
|
||
std::vector<char> vBuffer(nLength, '\0'); //创建用于存储格式化字符串的字符数组
|
||
int nWritten = _vsnprintf_s(&vBuffer[0], vBuffer.size(), nLength, lpcszFormat, marker);
|
||
if (nWritten > 0)
|
||
{
|
||
strResult = &vBuffer[0];
|
||
}
|
||
va_end(marker); //重置变量参数
|
||
}
|
||
if (strResult.empty())
|
||
{
|
||
return;
|
||
}
|
||
string strLog = strErrorPrefix;
|
||
strLog.append(GetTime()).append(strResult);
|
||
|
||
//写日志文件
|
||
Trace(strLog);
|
||
}
|
||
|
||
//写警告信息
|
||
void CLogger::TraceWarning(const char *lpcszFormat, ...)
|
||
{
|
||
//判断当前的写日志级别
|
||
if (EnumLogLevel::LogLevel_Warning > m_nLogLevel)
|
||
return;
|
||
string strResult;
|
||
if (NULL != lpcszFormat)
|
||
{
|
||
va_list marker = NULL;
|
||
va_start(marker, lpcszFormat); //初始化变量参数
|
||
size_t nLength = _vscprintf(lpcszFormat, marker) + 1; //获取格式化字符串长度
|
||
std::vector<char> vBuffer(nLength, '\0'); //创建用于存储格式化字符串的字符数组
|
||
int nWritten = _vsnprintf_s(&vBuffer[0], vBuffer.size(), nLength, lpcszFormat, marker);
|
||
if (nWritten > 0)
|
||
{
|
||
strResult = &vBuffer[0];
|
||
}
|
||
va_end(marker); //重置变量参数
|
||
}
|
||
if (strResult.empty())
|
||
{
|
||
return;
|
||
}
|
||
string strLog = strWarningPrefix;
|
||
strLog.append(GetTime()).append(strResult);
|
||
|
||
//写日志文件
|
||
Trace(strLog);
|
||
}
|
||
|
||
|
||
//写一般信息
|
||
void CLogger::TraceInfo(const char *lpcszFormat, ...)
|
||
{
|
||
//判断当前的写日志级别
|
||
if (EnumLogLevel::LogLevel_Info > m_nLogLevel)
|
||
return;
|
||
string strResult;
|
||
if (NULL != lpcszFormat)
|
||
{
|
||
va_list marker = NULL;
|
||
va_start(marker, lpcszFormat); //初始化变量参数
|
||
size_t nLength = _vscprintf(lpcszFormat, marker) + 1; //获取格式化字符串长度
|
||
std::vector<char> vBuffer(nLength, '\0'); //创建用于存储格式化字符串的字符数组
|
||
int nWritten = _vsnprintf_s(&vBuffer[0], vBuffer.size(), nLength, lpcszFormat, marker);
|
||
if (nWritten > 0)
|
||
{
|
||
strResult = &vBuffer[0];
|
||
}
|
||
va_end(marker); //重置变量参数
|
||
}
|
||
if (strResult.empty())
|
||
{
|
||
return;
|
||
}
|
||
string strLog = strInfoPrefix;
|
||
strLog.append(GetTime()).append(strResult);
|
||
|
||
//写日志文件
|
||
Trace(strLog);
|
||
}
|
||
|
||
//获取系统当前时间
|
||
string CLogger::GetTime()
|
||
{
|
||
time_t curTime;
|
||
time(&curTime);
|
||
tm tm1;
|
||
localtime_s(&tm1, &curTime);
|
||
//2016-01-01 21:30:00
|
||
string strTime = FormatString("%04d-%02d-%02d %02d:%02d:%02d ", tm1.tm_year + 1900, tm1.tm_mon + 1, tm1.tm_mday, tm1.tm_hour, tm1.tm_min, tm1.tm_sec);
|
||
|
||
return strTime;
|
||
}
|
||
|
||
//改变写日志级别
|
||
void CLogger::ChangeLogLevel(EnumLogLevel nLevel)
|
||
{
|
||
m_nLogLevel = nLevel;
|
||
}
|
||
|
||
//写文件操作
|
||
void CLogger::Trace(const string &strLog)
|
||
{
|
||
try
|
||
{
|
||
//进入临界区
|
||
EnterCriticalSection(&m_cs);
|
||
//若文件流没有打开,则重新打开
|
||
if (NULL == m_pFileStream)
|
||
{
|
||
fopen_s(&m_pFileStream, m_strLogFilePath.c_str(), "a+");
|
||
if (!m_pFileStream)
|
||
{
|
||
return;
|
||
}
|
||
}
|
||
//写日志信息到文件流
|
||
fprintf(m_pFileStream, "%s\n", strLog.c_str());
|
||
fflush(m_pFileStream);
|
||
//离开临界区
|
||
LeaveCriticalSection(&m_cs);
|
||
}
|
||
//若发生异常,则先离开临界区,防止死锁
|
||
catch (...)
|
||
{
|
||
LeaveCriticalSection(&m_cs);
|
||
}
|
||
}
|
||
|
||
string CLogger::GetAppPathA()
|
||
{
|
||
char szFilePath[MAX_PATH] = { 0 }, szDrive[MAX_PATH] = { 0 }, szDir[MAX_PATH] = { 0 }, szFileName[MAX_PATH] = { 0 }, szExt[MAX_PATH] = { 0 };
|
||
GetModuleFileNameA(NULL, szFilePath, sizeof(szFilePath));
|
||
_splitpath_s(szFilePath, szDrive, szDir, szFileName, szExt);
|
||
|
||
string str(szDrive);
|
||
str.append(szDir);
|
||
return str;
|
||
}
|
||
|
||
string CLogger::FormatString(const char *lpcszFormat, ...)
|
||
{
|
||
string strResult;
|
||
if (NULL != lpcszFormat)
|
||
{
|
||
va_list marker = NULL;
|
||
va_start(marker, lpcszFormat); //初始化变量参数
|
||
size_t nLength = _vscprintf(lpcszFormat, marker) + 1; //获取格式化字符串长度
|
||
std::vector<char> vBuffer(nLength, '\0'); //创建用于存储格式化字符串的字符数组
|
||
int nWritten = _vsnprintf_s(&vBuffer[0], vBuffer.size(), nLength, lpcszFormat, marker);
|
||
if (nWritten > 0)
|
||
{
|
||
strResult = &vBuffer[0];
|
||
}
|
||
va_end(marker); //重置变量参数
|
||
}
|
||
return strResult;
|
||
}
|
||
}
|