#include "Log.h" #include #include #include #include #include #include using namespace std; using namespace std::chrono; #define LOG_BUF_SIZE 20480 #define TIME_BUF_SIZE 64 Log Log::m_log; int Log::m_counter = 0; Log::Log() :LogTask(), m_bExit(false), m_fLog(nullptr), m_logLevel(LEVEL_NORMAL) { } Log::~Log() { // wait data write end while (!m_logQue.empty()) { milliseconds drua(10); this_thread::sleep_for(drua); } if (m_fLog) { fclose(m_fLog); m_fLog = nullptr; } } std::string Log::getSysTime() { time_t tt = system_clock::to_time_t(system_clock::now()); char timeBuf[TIME_BUF_SIZE]; memset(timeBuf, 0, sizeof(timeBuf)); struct tm* pTime = localtime(&tt); sprintf(timeBuf, "%4d/%02d/%02d %02d:%02d:%02d", pTime->tm_year + 1900, pTime->tm_mon + 1, pTime->tm_mday, pTime->tm_hour, pTime->tm_min, pTime->tm_sec); return string(timeBuf); } Log& Log::getInstance() { return m_log; } void Log::init(int level, const char* pLogModuleName) { std::unique_lock lck(m_mutex); m_logLevel = level; // 每次init都重新打开一个log文件 if (m_fLog != nullptr) { fclose(m_fLog); m_fLog = nullptr; } if (m_fLog == nullptr && m_logLevel > 0) { time_t tt = system_clock::to_time_t(system_clock::now()); char timeBuf[TIME_BUF_SIZE]; memset(timeBuf, 0, sizeof(timeBuf)); struct tm* pTime = localtime(&tt); sprintf(timeBuf, "%4d-%02d-%02d %02d-%02d-%02d", pTime->tm_year + 1900, pTime->tm_mon + 1, pTime->tm_mday, pTime->tm_hour, pTime->tm_min, pTime->tm_sec); string strpath = "./log/log_"; if (pLogModuleName) { strpath += pLogModuleName; strpath += "_"; } strpath += timeBuf; strpath += ".txt"; m_fLog = fopen(strpath.c_str(), "a+"); // 开启写入文件线程 m_log.log_write_thread(); } } void Log::log(int level, const char* file, const char* func, int lineNo, const char* cFormat, ...) { if (level <= LEVEL_NORMAL || level > LEVEL_DEBUG) return; va_list args; ostringstream oss; //oss << file << ' : ' << lineNo << ' : ' << func << "() \n"; oss << lineNo << " : " << func << "() ==> " << cFormat << "\n"; va_start(args, cFormat); push_log(level, const_cast(oss.str().c_str()), args); va_end(args); } void Log::log2(int level, const char* cFormat, ...) { if (level <= LEVEL_NORMAL || level > LEVEL_DEBUG) return; va_list args; va_start(args, cFormat); push_log(level, (char*)cFormat, args); va_end(args); } void Log::debugBin(const char* szInfo, uint8_t* szData, uint32_t nDataLen) { // 不输出debug信息 if (m_logLevel < LEVEL_DEBUG) return; char szBuf[LOG_BUF_SIZE]; hex2Str(szBuf, sizeof(szBuf), szData, nDataLen); log2(LEVEL_DEBUG, "%s %s", szInfo, szBuf); } void Log::debugStr(const char* szInfo, const char* cFormat, ...) { if (m_logLevel < LEVEL_DEBUG) return; va_list args; va_start(args, cFormat); char logbuf[LOG_BUF_SIZE]; memset(logbuf, 0, sizeof(logbuf)); string&& sysTime = getSysTime(); sprintf(logbuf, "%s [DEBUG] %s", sysTime.c_str(), szInfo); size_t lens = strlen(logbuf); vsnprintf(logbuf + lens, LOG_BUF_SIZE - 1 - lens, cFormat, args);// last bit'\0' va_end(args); string LogString(logbuf); push_logstr(LogString); } void Log::info(const char* szInfo, const char* cFormat, ...) { if (m_logLevel < LEVEL_INFOR) return; va_list args; va_start(args, cFormat); char logbuf[LOG_BUF_SIZE]; memset(logbuf, 0, sizeof(logbuf)); string&& sysTime = getSysTime(); sprintf(logbuf, "%s %s", sysTime.c_str(), szInfo); size_t lens = strlen(logbuf); vsnprintf(logbuf + lens, LOG_BUF_SIZE - 1 - lens, cFormat, args);// last bit'\0' va_end(args); string LogString(logbuf); push_logstr(LogString); } void Log::hex2Str(char* outBuf, uint32_t nbufLen, uint8_t* szData, uint32_t nDataLen) { memset(outBuf, 0, nbufLen); uint32_t i = 0, j = 0; for (; i < nDataLen && j < nbufLen - 4; ++i) { if (i % 24 == 0) { sprintf(outBuf + j, "%s", "\n"); j += 1; } sprintf(outBuf + j, "%02X ", szData[i]); j += 3; } sprintf(outBuf + j, "%s", "\n"); } void Log::push_log(int level, char* cFormat, va_list vlist) { if (level <= m_logLevel) { char levelstr[20]; switch (level) { case LEVEL_DEBUG: strcpy(levelstr, "DEBUG"); break; case LEVEL_ERROR: strcpy(levelstr, "ERROR"); break; case LEVEL_INFOR: default: strcpy(levelstr, "INFOR"); break; } char logbuf[LOG_BUF_SIZE]; memset(logbuf, 0, sizeof(logbuf)); string&& sysTime = getSysTime(); sprintf(logbuf, "%s [%s] ", sysTime.c_str(), levelstr); int lens = strlen(logbuf); vsnprintf(logbuf + lens, LOG_BUF_SIZE - 1 - lens, cFormat, vlist);// last bit'\0' string LogString(logbuf); push_logstr(LogString); } } void Log::push_logstr(std::string& strLog) { std::unique_lock lck(m_mutex); m_logQue.push(strLog); m_cv.notify_all(); } void Log::quit() { std::unique_lock lck(m_mutex); m_bExit = true; m_cv.notify_all(); } std::string Log::pop_log() { std::string LogString; std::unique_lock lck(m_mutex); if (m_logQue.empty()) { m_cv.wait(lck); } if (!m_logQue.empty()) { LogString = m_logQue.front(); m_logQue.pop(); } return LogString; } void Log::run() { while (!m_bExit) { std::string LogString = pop_log(); if (m_fLog && !LogString.empty()) { fprintf(m_fLog, "%s", LogString.c_str()); fflush(m_fLog); } fprintf(stderr, "%s", LogString.c_str()); } }