使用C++编写自定义的日志文件,无需第三方库,包含输出日志信息的时间、类别、代码文件名、行数、线程号以及日志内容。
#pragma once
#include <string>
#include <iostream>
#include <fstream>
#ifdef WIN32
#include <io.h>
#include <direct.h>
#include <windows.h>
#else
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/syscall.h>
#endif
#include <time.h>
#include <stdlib.h>
#include <stdio.h>
#include <mutex>
#include <sstream>
#include <stdarg.h>
#define gettid() syscall(__NR_gettid)
#define MAX_LEN 1024
static std::mutex logMutex;
enum LogLevelEnum
{
INFO = 0,
DEBUG = 1,
WARN = 2,
ERROR = 3,
CRITICAL = 4,
};
class logInf
{
public:
logInf(){}
logInf(std::string logDir, std::string prjname)
{
InitialStrLog(logDir, prjname);
}
~logInf(){}
std::time_t getTimeStamp()
{
std::chrono::time_point<std::chrono::system_clock,std::chrono::milliseconds> tp = std::chrono::time_point_cast<std::chrono::milliseconds>(std::chrono::system_clock::now());
auto tmp=std::chrono::duration_cast<std::chrono::milliseconds>(tp.time_since_epoch());
std::time_t timestamp = tmp.count();
return timestamp;
}
std::tm* gettm(uint64_t timestamp)
{
uint64_t milli = timestamp;
milli += (uint64_t)8*60*60*1000;//转换时区,北京时间+8小时
auto mTime = std::chrono::milliseconds(milli);
auto tp=std::chrono::time_point<std::chrono::system_clock,std::chrono::milliseconds>(mTime);
auto tt = std::chrono::system_clock::to_time_t(tp);
std::tm* now = std::gmtime(&tt);
return now;
}
std::string getTimeStr()
{
time_t timep;
timep = getTimeStamp();
struct tm *info;
info = gettm(timep);
char tmp[1000] = {0};
sprintf(tmp, "%04d-%02d-%02d %02d:%02d:%02d.%03ld", info->tm_year+1900, info->tm_mon+1, info->tm_mday, info->tm_hour, info->tm_min, info->tm_sec, timep%1000000);
return tmp;
}
void InitialStrLog(std::string logDir, std::string prjname)
{
strlogPath = logDir + "/" + prjname;
#ifdef WIN32
int iRet = _access(strlogPath.c_str(), 0);
#else
int iRet = access(strlogPath.c_str(), 0);
#endif
if (iRet != 0)
{
std::ofstream ofs(strlogPath, std::ios::app);
if (ofs.is_open())
{
std::cout << "file is open !" << std::endl;
ofs.close();
}
}
}
inline void LogString(std::string strInf, LogLevelEnum nLevel, std::string filename, int nrow)
{
time_t timep;
time(&timep);
char tmp[64];
strftime(tmp, 23, "%Y-%m-%d %H:%m:%s", localtime(&timep));
std::string strTime = getTimeStr(); //tmp;
std::string strTimeOut = "{" + strTime + "}";
std::string strloglevel;
if (nLevel == LogLevelEnum::INFO)
{
strloglevel = "{INFO}";
}
else if (nLevel == LogLevelEnum::DEBUG)
{
strloglevel = "{DEBUG}";
}
else if (nLevel == LogLevelEnum::WARN)
{
strloglevel = "{WARN}";
}
else if (nLevel == LogLevelEnum::ERROR)
{
strloglevel = "{ERROR}";
}
else if (nLevel == LogLevelEnum::CRITICAL)
{
strloglevel = "{CRITICAL}";
}
int findex = filename.find_last_of("/");
if(findex < 0) findex = 0;
std::string strfilename = filename.substr(findex+1);
std::string strFuncName = "{" + strfilename + "}";
int lineRow = __LINE__;
std::stringstream ss;
ss << lineRow;
std::string strRowNum = "{" + ss.str() + "}";
std::stringstream sthread;
int nTreadID;
#ifdef WIN32
nTreadID = GetCurrentThreadId();
#else
nTreadID = gettid();
#endif
sthread << nTreadID;
std::string strTreadID = "{" + sthread.str() + "}";
logMutex.lock();
std::string strlineInf = strTimeOut + strloglevel + strFuncName + strRowNum + strTreadID + ": " + strInf;
std::ofstream ofs(strlogPath, std::ios::app);
if (ofs.is_open())
{
ofs << strlineInf << std::endl;
std::cout<<strlineInf<<std::endl;
}
logMutex.unlock();
}
inline void LogString(LogLevelEnum nLevel, std::string filename, int nrow,const char* format, ...)
{
char message[MAX_LEN];
va_list args;
va_start(args, format);
vsnprintf (message, MAX_LEN, format, args);
va_end(args);
time_t timep= time(NULL);
char tmp[64];
strftime(tmp, 23, "%Y-%m-%d %H:%M:%S", localtime(&timep));
std::string strTime = getTimeStr(); //tmp;
std::string strTimeOut = "{" + strTime + "}";
std::string strloglevel;
if (nLevel == LogLevelEnum::INFO)
{
strloglevel = "{INFO}";
}
else if (nLevel == LogLevelEnum::DEBUG)
{
strloglevel = "{DEBUG}";
}
else if (nLevel == LogLevelEnum::WARN)
{
strloglevel = "{WARN}";
}
else if (nLevel == LogLevelEnum::ERROR)
{
strloglevel = "{ERROR}";
}
else if (nLevel == LogLevelEnum::CRITICAL)
{
strloglevel = "{CRITICAL}";
}
int findex = filename.find_last_of("/");
if(findex < 0) findex = 0;
std::string strfilename = filename.substr(findex+1);
std::string strFuncName = "{" + strfilename + "}";
int lineRow = nrow;
std::stringstream ss;
ss << lineRow;
std::string strRowNum = "{" + ss.str() + "}";
std::stringstream sthread;
int nTreadID;
#ifdef WIN32
nTreadID = GetCurrentThreadId();
#else
nTreadID = gettid();
#endif
sthread << nTreadID;
std::string strTreadID = "{" + sthread.str() + "}";
logMutex.lock();
std::string strInf = message;
std::string strlineInf = strTimeOut + strloglevel + strFuncName + strRowNum + strTreadID + ": " + strInf;
std::ofstream ofs(strlogPath, std::ios::app);
if (ofs.is_open())
{
ofs << strlineInf << std::endl;
std::cout<<strlineInf<<std::endl;
}
logMutex.unlock();
}
private:
std::string strlogPath;
};