logger.h
#include <mutex>
#include <condition_variable>
#include <list>
//struct FILE;
#define loginfo(...) Logger::GetInstance().AddToQueue("INFO", __FILE__, __LINE__, __PRETTY_FUNCTION__, __VA_ARGS__)
#define logwarning(...) Logger::GetInstance().AddToQueue("WARNING", __FILE__, __LINE__, __PRETTY_FUNCTION__, __VA_ARGS__)
#define logerror(...) Logger::GetInstance().AddToQueue("ERROR", __FILE__, __LINE__, __PRETTY_FUNCTION__, __VA_ARGS__)
class Logger
{
public:
static Logger& GetInstance();
void SetFilePath(const char* filename);
bool Start();
void Stop();
void AddToQueue(const char* pszLevel, const char* pszFile, int lineNo, const char* pszFuncSig, char* pszFmt, ...);
private:
Logger() = default;
Logger(const Logger& rhs) = delete;
Logger& operator =(Logger& rhs) = delete;
void threadfunc();
private:
std::string filename_;
std::string filepath_;
FILE* fp_{};
std::shared_ptr<std::thread> spthread_;
std::mutex mutex_;
std::condition_variable cv_; //有新的日志到来的标识
bool exit_{false};
std::list<std::string> queue_;
};
#endif // LOGGER_H
logger.cpp
#include "logger.h"
#include <time.h>
#include <stdio.h>
#include <memory>
#include <stdarg.h>
Logger& Logger::GetInstance()
{
static Logger logger;
return logger;
}
void Logger::SetFilePath(const char* filepath)
{
filepath_ = filepath;
}
bool Logger::Start()
{
std::string strflag;
if(filepath_.empty()){
filepath_ = "/opt/Log";
}
strflag = "mkdir -p "+filepath_;
system(strflag.c_str());
time_t now = time(NULL);
struct tm* t = localtime(&now);
char timestr[1024] = { 0 };
// sprintf(timestr, "./opt/logger/logger/logger/%04d%02d%02d%02d%02d%02d.log", t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
sprintf(timestr, "%04d%02d%02d%02d.log", t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,t->tm_sec);
filename_ = filepath_+"/"+timestr;
fp_ = fopen(filename_.c_str(), "wt+");
if (fp_ == NULL)
return false;
spthread_.reset(new std::thread(std::bind(&Logger::threadfunc, this)));
return true;
}
void Logger::Stop()
{
exit_ = true;
cv_.notify_one();
//等待时间线程结束
spthread_->join();
}
void Logger::AddToQueue(const char* pszLevel, const char* pszFile, int lineNo, const char* pszFuncSig, char* pszFmt, ...)
{
char msg[256] = { 0 };
va_list vArgList;
va_start(vArgList, pszFmt);
vsnprintf(msg, 256, pszFmt, vArgList);
va_end(vArgList);
time_t now = time(NULL);
struct tm* tmstr = localtime(&now);
char timeflag[1024] = { 0 };
sprintf(timeflag, "%04d%02d%02d%02d.log", tmstr->tm_year + 1900, tmstr->tm_mon + 1, tmstr->tm_mday,tmstr->tm_sec);
std::string timestr = filepath_+"/"+timeflag;
if(filename_.compare(timestr)!=0){
if (fp_ == NULL)
return;
filename_ = timestr;
fflush(fp_);
fp_ = fopen(filename_.c_str(), "wt+");
if (fp_ == NULL)
return;
}
char content[512] = { 0 };
sprintf(content, "[%04d-%02d-%02d %02d:%02d:%02d][%s][0x%04x][%s:%d %s]%s\n",
tmstr->tm_year + 1900,
tmstr->tm_mon + 1,
tmstr->tm_mday,
tmstr->tm_hour,
tmstr->tm_min,
tmstr->tm_sec,
pszLevel,
std::this_thread::get_id(),
pszFile,
lineNo,
pszFuncSig,
msg);
{
std::lock_guard<std::mutex> guard(mutex_);
queue_.emplace_back(content);
}
cv_.notify_one();
}
void Logger::threadfunc()
{
if (fp_ == NULL)
return;
while (!exit_)
{
//写日志
std::unique_lock<std::mutex> guard(mutex_);
while (queue_.empty())
{
if (exit_)
return;
cv_.wait(guard);
}
//写日志
const std::string& str = queue_.front();
fwrite((void*)str.c_str(), str.length(), 1, fp_);
fflush(fp_);
queue_.pop_front();
}
}
使用在main.c 包含logger.h头文件
main函数中添加
Logger::GetInstance().SetFilePath("./opt/Log");//可以不用,在logger.cpp中修改
Logger::GetInstance().Start();
其他文件使用添加logger.h
loginfo(“1111”);