需求:
1、以当前日期为文件名,新建或追加写日志。
2、日志记录到队列中,通过线程再从队列中逐条去除写日志文件。
3、不要太大、太复杂,一个h文件和一个cpp文件足矣!
1、以当前日期为文件名,新建或追加写日志。
2、日志记录到队列中,通过线程再从队列中逐条去除写日志文件。
3、不要太大、太复杂,一个h文件和一个cpp文件足矣!
解决方案
12
http://blog.csdn.net/chenyusiyuan/article/details/7726614
1
log4cxx
25
loglite.cpp
#include "common_include.h" #include "LogLite.h" namespace fs = boost::filesystem; LogLite::LogLite(const std::string& path, const std::string& baseFileName): m_path(path), m_baseFileName(baseFileName), m_file(NULL), m_fileNum(0), m_stop(false) { fs::create_directories(path); CreateLogFile(); m_thread.reset(new std::thread(&LogLite::WriteThreadHandler, this)); } LogLite::~LogLite() { m_stop = true; m_cv.notify_one(); m_thread->join(); } void LogLite::CreateLogFile() { if(m_file != NULL) { fclose(m_file); m_file = NULL; } time_t t = time(NULL); struct tm* now = localtime(&t); char name[UCHAR_MAX] = {0}; snprintf(name, UCHAR_MAX, "%s/%s_%04d%02d%02d%02d%02d%02d_%05d.log", m_path.c_str(), m_baseFileName.c_str(), now->tm_year + 1900, now->tm_mon + 1, now->tm_mday, now->tm_hour, now->tm_min, now->tm_sec, ++m_fileNum); m_file = fopen(name, "w"); assert(m_file != NULL); } void LogLite::Write(const char* level, int line, const char* fileName, const char* funcName, const char* fmt, ...) { struct Item item = {0}; va_list ap; va_start(ap, fmt); int n = vsnprintf(item.text, FORMAT_TEXT_LEN, fmt, ap); va_end(ap); if(n > 0) { item.text[std::min(n, (int)FORMAT_TEXT_LEN)] = "\n"; item.text[std::min(n + 1, (int)FORMAT_TEXT_LEN)] = "\n"; item.size = std::min(n + 2, (int)FORMAT_TEXT_LEN); struct Item info = {0}; CreateItemInfo(level, line, fileName, funcName, info); { std::unique_lock<std::mutex> lock(m_mutex); m_items.push_back(info); m_items.push_back(item); } } if(m_items.size() > WRITE_ITEM_COUNT) { m_cv.notify_one(); } } void LogLite::WriteHex(const char* level, int line, const char* fileName, const char* funcName, const void* buf, size_t size) { struct Item item = {0}; int n = 0; for(size_t i = 0; i < size && n < FORMAT_TEXT_LEN; i++) { int c = snprintf(&item.text[n], FORMAT_TEXT_LEN - n, "%02X ", *((uint8_t*)buf + i)); n += c; } item.text[std::min(n, (int)FORMAT_TEXT_LEN)] = "\n"; item.text[std::min(n + 1, (int)FORMAT_TEXT_LEN)] = "\n"; item.size = std::min(n + 2, (int)FORMAT_TEXT_LEN); struct Item info = {0}; CreateItemInfo(level, line, fileName, funcName, info); { std::unique_lock<std::mutex> lock(m_mutex); m_items.push_back(info); m_items.push_back(item); } if(m_items.size() > WRITE_ITEM_COUNT) { m_cv.notify_one(); } } void LogLite::CreateItemInfo(const char* level, int line, const char* fileName, const char* funcName, struct Item& item) { time_t t = time(NULL); struct tm* now = localtime(&t); struct timeval tv; gettimeofday(&tv, NULL); int n = snprintf(item.text, FORMAT_TEXT_LEN, "%s %04d-%02d-%02d %02d:%02d:%02d.%03ld line=%04d file=%s func=%s thread=%u\n", level, now->tm_year + 1900, now->tm_mon + 1, now->tm_mday, now->tm_hour, now->tm_min, now->tm_sec, tv.tv_usec / 1000, line, fileName, funcName, std::this_thread::get_id()); item.size = n; } void LogLite::KeepFileCount() const { std::set<std::string> ls; boost::system::error_code e; fs::directory_iterator end; for(fs::directory_iterator it(fs::path(m_path), e); it != end; ++it) { if(fs::is_regular_file(*it, e)) { ls.insert(it->path().string()); } } if(ls.size() > MAX_FILE_COUNT) { size_t n = ls.size() - MAX_FILE_COUNT; while(n--) { std::set<std::string>::iterator it = ls.begin(); const std::string& s = *it; fs::remove(s, e); ls.erase(it); } } } void LogLite::WriteThreadHandler() { assert(m_file != NULL); while(!m_stop) { std::vector<struct Item> items; { std::unique_lock<std::mutex> lock(m_mutex); m_cv.wait_for(lock, std::chrono::milliseconds(FLUSH_MILLISEC), [&]() { return m_stop; }); if(m_stop) break; m_items.swap(items); } for(const struct Item& item: items) { fwrite(item.text, item.size, 1, m_file); } fflush(m_file); //多次写入后再刷新至硬盘 if(ftell(m_file) >= MAX_FILE_SIZE) { CreateLogFile(); } KeepFileCount(); } assert(m_file != NULL); fclose(m_file); }
1
25
仅供参考:
//循环向a函数每次发送200个字节长度(这个是固定的)的buffer, //a函数中需要将循环传进来的buffer,组成240字节(也是固定的)的新buffer进行处理, //在处理的时候每次从新buffer中取两个字节打印 #ifdef _MSC_VER #pragma warning(disable:4996) #endif #include <stdio.h> #include <stdlib.h> #include <string.h> #ifdef _MSC_VER #include <windows.h> #include <process.h> #include <io.h> #define MYVOID void #define vsnprintf _vsnprintf #else #include <unistd.h> #include <sys/time.h> #include <pthread.h> #define CRITICAL_SECTION pthread_mutex_t #define MYVOID void * #endif //Log{ #define MAXLOGSIZE 20000000 #define MAXLINSIZE 16000 #include <time.h> #include <sys/timeb.h> #include <stdarg.h> char logfilename1[]="MyLog1.log"; char logfilename2[]="MyLog2.log"; static char logstr[MAXLINSIZE+1]; char datestr[16]; char timestr[16]; char mss[4]; CRITICAL_SECTION cs_log; FILE *flog; #ifdef _MSC_VER void Lock(CRITICAL_SECTION *l) { EnterCriticalSection(l); } void Unlock(CRITICAL_SECTION *l) { LeaveCriticalSection(l); } void sleep_ms(int ms) { Sleep(ms); } #else void Lock(CRITICAL_SECTION *l) { pthread_mutex_lock(l); } void Unlock(CRITICAL_SECTION *l) { pthread_mutex_unlock(l); } void sleep_ms(int ms) { usleep(ms*1000); } #endif void LogV(const char *pszFmt,va_list argp) { struct tm *now; struct timeb tb; if (NULL==pszFmt||0==pszFmt[0]) return; vsnprintf(logstr,MAXLINSIZE,pszFmt,argp); ftime(&tb); now=localtime(&tb.time); sprintf(datestr,"%04d-%02d-%02d",now->tm_year+1900,now->tm_mon+1,now->tm_mday); sprintf(timestr,"%02d:%02d:%02d",now->tm_hour ,now->tm_min ,now->tm_sec ); sprintf(mss,"%03d",tb.millitm); printf("%s %s.%s %s",datestr,timestr,mss,logstr); flog=fopen(logfilename1,"a"); if (NULL!=flog) { fprintf(flog,"%s %s.%s %s",datestr,timestr,mss,logstr); if (ftell(flog)>MAXLOGSIZE) { fclose(flog); if (rename(logfilename1,logfilename2)) { remove(logfilename2); rename(logfilename1,logfilename2); } } else { fclose(flog); } } } void Log(const char *pszFmt,...) { va_list argp; Lock(&cs_log); va_start(argp,pszFmt); LogV(pszFmt,argp); va_end(argp); Unlock(&cs_log); } //Log} #define ASIZE 200 #define BSIZE 240 #define CSIZE 2 char Abuf[ASIZE]; char Cbuf[CSIZE]; CRITICAL_SECTION cs_HEX ; CRITICAL_SECTION cs_BBB ; struct FIFO_BUFFER { int head; int tail; int size; char data[BSIZE]; } BBB; int No_Loop=0; void HexDump(int cn,char *buf,int len) { int i,j,k; char binstr[80]; Lock(&cs_HEX); for (i=0;i<len;i++) { if (0==(i%16)) { sprintf(binstr,"%03d %04x -",cn,i); sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]); } else if (15==(i%16)) { sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]); sprintf(binstr,"%s ",binstr); for (j=i-15;j<=i;j++) { sprintf(binstr,"%s%c",binstr,("!"<buf[j]&&buf[j]<="~")?buf[j]:"."); } Log("%s\n",binstr); } else { sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]); } } if (0!=(i%16)) { k=16-(i%16); for (j=0;j<k;j++) { sprintf(binstr,"%s ",binstr); } sprintf(binstr,"%s ",binstr); k=16-k; for (j=i-k;j<i;j++) { sprintf(binstr,"%s%c",binstr,("!"<buf[j]&&buf[j]<="~")?buf[j]:"."); } Log("%s\n",binstr); } Unlock(&cs_HEX); } int GetFromRBuf(int cn,CRITICAL_SECTION *cs,struct FIFO_BUFFER *fbuf,char *buf,int len) { int lent,len1,len2; lent=0; Lock(cs); if (fbuf->size>=len) { lent=len; if (fbuf->head+lent>BSIZE) { len1=BSIZE-fbuf->head; memcpy(buf ,fbuf->data+fbuf->head,len1); len2=lent-len1; memcpy(buf+len1,fbuf->data ,len2); fbuf->head=len2; } else { memcpy(buf ,fbuf->data+fbuf->head,lent); fbuf->head+=lent; } fbuf->size-=lent; } Unlock(cs); return lent; } MYVOID thdB(void *pcn) { char *recv_buf; int recv_nbytes; int cn; int wc; int pb; cn=(int)pcn; Log("%03d thdB thread begin...\n",cn); while (1) { sleep_ms(10); recv_buf=(char *)Cbuf; recv_nbytes=CSIZE; wc=0; while (1) { pb=GetFromRBuf(cn,&cs_BBB,&BBB,recv_buf,recv_nbytes); if (pb) { Log("%03d recv %d bytes\n",cn,pb); HexDump(cn,recv_buf,pb); sleep_ms(1); } else { sleep_ms(1000); } if (No_Loop) break;// wc++; if (wc>3600) Log("%03d %d==wc>3600!\n",cn,wc); } if (No_Loop) break;// } #ifndef _MSC_VER pthread_exit(NULL); #endif } int PutToRBuf(int cn,CRITICAL_SECTION *cs,struct FIFO_BUFFER *fbuf,char *buf,int len) { int lent,len1,len2; Lock(cs); lent=len; if (fbuf->size+lent>BSIZE) { lent=BSIZE-fbuf->size; } if (fbuf->tail+lent>BSIZE) { len1=BSIZE-fbuf->tail; memcpy(fbuf->data+fbuf->tail,buf ,len1); len2=lent-len1; memcpy(fbuf->data ,buf+len1,len2); fbuf->tail=len2; } else { memcpy(fbuf->data+fbuf->tail,buf ,lent); fbuf->tail+=lent; } fbuf->size+=lent; Unlock(cs); return lent; } MYVOID thdA(void *pcn) { char *send_buf; int send_nbytes; int cn; int wc; int a; int pa; cn=(int)pcn; Log("%03d thdA thread begin...\n",cn); a=0; while (1) { sleep_ms(100); memset(Abuf,a,ASIZE); a=(a+1)%256; if (16==a) {No_Loop=1;break;}//去掉这句可以让程序一直循环直到按Ctrl+C或Ctrl+Break或当前目录下存在文件No_Loop send_buf=(char *)Abuf; send_nbytes=ASIZE; Log("%03d sending %d bytes\n",cn,send_nbytes); HexDump(cn,send_buf,send_nbytes); wc=0; while (1) { pa=PutToRBuf(cn,&cs_BBB,&BBB,send_buf,send_nbytes); Log("%03d sent %d bytes\n",cn,pa); HexDump(cn,send_buf,pa); send_buf+=pa; send_nbytes-=pa; if (send_nbytes<=0) break;// sleep_ms(1000); if (No_Loop) break;// wc++; if (wc>3600) Log("%03d %d==wc>3600!\n",cn,wc); } if (No_Loop) break;// } #ifndef _MSC_VER pthread_exit(NULL); #endif } int main() { #ifdef _MSC_VER InitializeCriticalSection(&cs_log); InitializeCriticalSection(&cs_HEX ); InitializeCriticalSection(&cs_BBB ); #else pthread_t threads[2]; int threadsN; int rc; pthread_mutex_init(&cs_log,NULL); pthread_mutex_init(&cs_HEX,NULL); pthread_mutex_init(&cs_BBB,NULL); #endif Log("Start===========================================================\n"); BBB.head=0; BBB.tail=0; BBB.size=0; #ifdef _MSC_VER _beginthread((void(__cdecl *)(void *))thdA,0,(void *)1); _beginthread((void(__cdecl *)(void *))thdB,0,(void *)2); #else threadsN=0; rc=pthread_create(&(threads[threadsN++]),NULL,thdA,(void *)1);if (rc) Log("%d=pthread_create %d error!\n",rc,threadsN-1); rc=pthread_create(&(threads[threadsN++]),NULL,thdB,(void *)2);if (rc) Log("%d=pthread_create %d error!\n",rc,threadsN-1); #endif if (!access("No_Loop",0)) { remove("No_Loop"); if (!access("No_Loop",0)) { No_Loop=1; } } while (1) { sleep_ms(1000); if (No_Loop) break;// if (!access("No_Loop",0)) { No_Loop=1; } } sleep_ms(3000); Log("End=============================================================\n"); #ifdef _MSC_VER DeleteCriticalSection(&cs_BBB ); DeleteCriticalSection(&cs_HEX ); DeleteCriticalSection(&cs_log); #else pthread_mutex_destroy(&cs_BBB); pthread_mutex_destroy(&cs_HEX); pthread_mutex_destroy(&cs_log); #endif return 0; }
21
头文件
#pragma once #include <Windows.h> #include <stdio.h> #include <time.h> #include <sys/timeb.h> #define LOG_DEBUG 1 #define LOG_WARING 2 #define LOG_ERROR 3 #define CURRENT_LEVEL LOG_DEBUG #define ADD_LOG(fmt, ...) CLog::GetInstance()->AddLog(fmt,__FILE__,__LINE__,CURRENT_LEVEL) class CLog { public: static CLog* GetInstance(); public: // 添加日志 int AddLog(char* pszLogTxt,char* FileName = __FILE__,int nLine = __LINE__,int log_level = LOG_DEBUG); // 设置日志文件存放路径 void SetLogPath(const char* szLogPath); // 清空日志文件 int ClearLog(); protected: char m_szLogPath[MAX_PATH]; // char m_szLogPath_Tmp[MAX_PATH]; FILE* m_pLogFile; struct tm m_current_time; // 构造线程安全类 CRITICAL_SECTION m_cs; private: CLog(); ~CLog(); static CLog* m_pLog; }; class CAutoLog { public: CAutoLog(char* pszLogTxt,int log_level = LOG_DEBUG) { int nLen = strlen(pszLogTxt); char* pBuf = new char[nLen+10]; memcpy(pBuf,pszLogTxt,nLen); memcpy(pBuf+nLen,"===Begin",9); ADD_LOG(pBuf); delete[] pBuf; m_LogTxt = pszLogTxt; } ~CAutoLog() { int nLen = strlen(m_LogTxt); char* pBuf = new char[nLen+10]; memcpy(pBuf,m_LogTxt,nLen); memcpy(pBuf+nLen,"===END",7); CLog::GetInstance()->AddLog(pBuf); delete[] pBuf; } private: char* m_LogTxt; };
///源文件
#include "Log.h" #include <string> using namespace std; CLog* CLog::m_pLog = NULL; // This is the constructor of a class that has been exported. // see Log.h for the class definition CLog::CLog() { // 默认放在程序运行目录下 char szConfigPath[MAX_PATH]={0}; //获取EXE全路径 char szExePath[MAX_PATH]={0}; GetModuleFileNameA( NULL, (LPCH)szExePath, MAX_PATH ); char *tmp=szExePath; while(strchr(tmp,"\") != NULL) //截取全路径名 { tmp = strchr(tmp,"\") + 1; } szExePath[strlen(szExePath) - strlen(tmp)] = "\0"; // sprintf_s( m_szLogPath,"%srun.log", szExePath ); m_pLogFile = NULL; InitializeCriticalSection(&m_cs); struct timeb tp; struct tm *tm; ftime(&tp); tm = localtime(&tp.time); m_current_time = *tm; // time_t t = time(0); char szTime[MAX_PATH]; CreateDirectoryA( "Log", NULL); sprintf_s(m_szLogPath ,"%slog\%.4d_%.2d_%.2d.log",szExePath,1900+tm->tm_year, 1 + tm->tm_mon,tm->tm_mday);//sizeof("d:\8.0平台_01_01.log") // EnterCriticalSection(&m_cs); m_pLogFile = fopen(m_szLogPath, "a+"); } CLog::~CLog() { fclose(m_pLogFile); if(m_pLog) { delete m_pLog; m_pLog = NULL; } }; int CLog::AddLog( char* pszLogTxt,char* FileName /*= __FILE__*/,int nLine /*= __LINE__*/ ,int log_level /*= LOG_DEBUG*/) { if (log_level<CURRENT_LEVEL) { return 1; } struct timeb tp; struct tm *tm; ftime(&tp); tm = localtime(&tp.time); // time_t t = time(0); char szTime[MAX_PATH]; sprintf_s(szTime, "%.4d-%.2d-%.2d %.2d:%.2d:%.2d.%.3d", 1900+ tm->tm_year, 1 + tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, tp.millitm); // CreateDirectory( "d:\Log ", NULL); // sprintf_s(m_szLogPath_Tmp ,"d:\log\8.0平台_%.2d_%.2d.log",1 + tm->tm_mon,tm->tm_mday);//sizeof("d:\8.0平台_01_01.log") // EnterCriticalSection(&m_cs); if ((m_current_time.tm_mday!=tm->tm_mday)|| (m_current_time.tm_mon!=tm->tm_mon)) { EnterCriticalSection(&m_cs); fclose(m_pLogFile); char szExePath[MAX_PATH]={0}; GetModuleFileNameA( NULL, (LPCH)szExePath, MAX_PATH ); char *tmp=szExePath; while(strchr(tmp,"\") != NULL) //截取全路径名 { tmp = strchr(tmp,"\") + 1; } szExePath[strlen(szExePath) - strlen(tmp)] = "\0"; // sprintf_s(m_szLogPath ,"%slog\_%.2d_%.2d.log",szExePath,1 + tm->tm_mon,tm->tm_mday); sprintf_s(m_szLogPath ,"%slog\%.4d_%.2d_%.2d.log",szExePath,1900+tm->tm_year, 1 + tm->tm_mon,tm->tm_mday); // strcpy_s(m_szLogPath,m_szLogPath_Tmp); m_pLogFile = fopen(m_szLogPath, "a+"); LeaveCriticalSection(&m_cs); } if (m_pLogFile == 0) { return -1; } string strFile = FileName; strFile = strFile.substr(strFile.find_last_of("\")+1,strFile.length()); int nLen = fprintf(m_pLogFile, "%s:%d [%s]: %s\n",strFile.c_str(),nLine, szTime, pszLogTxt); fflush(m_pLogFile); // fclose(m_pLogFile); // LeaveCriticalSection(&m_cs); return 0; } void CLog::SetLogPath(const char* szLogPath) { char buffP[100] ={0}; sprintf_s(buffP,"%s\log",szLogPath); CreateDirectoryA(buffP,NULL); fclose(m_pLogFile); struct timeb tp; struct tm *tm; ftime(&tp); tm = localtime(&tp.time); m_current_time = *tm; // time_t t = time(0); char szTime[MAX_PATH]; strcpy_s(m_szLogPath, szLogPath); // CreateDirectoryA( "Log", NULL); sprintf_s(m_szLogPath ,"%slog\%.4d_%.2d_%.2d.log",m_szLogPath,1900+tm->tm_year, 1 + tm->tm_mon,tm->tm_mday);//sizeof("d:\8.0平台_01_01.log") // EnterCriticalSection(&m_cs); m_pLogFile = fopen(m_szLogPath, "a+"); } int CLog::ClearLog() { EnterCriticalSection(&m_cs); m_pLogFile = fopen(m_szLogPath, "w"); fclose(m_pLogFile); LeaveCriticalSection(&m_cs); return 0; } CLog* CLog::GetInstance() { if(NULL == m_pLog) { m_pLog = new CLog; } return m_pLog; }
10
MFC版本的。
https://github.com/Hale-Lee/UltraLog
https://github.com/Hale-Lee/UltraLog
20
http://www.oschina.net/code/snippet_1402899_26572
http://www.cnblogs.com/wainiwann/archive/2013/01/30/2882308.html
http://junsky.iteye.com/blog/781147
http://www.cnblogs.com/wainiwann/archive/2013/01/30/2882308.html
http://junsky.iteye.com/blog/781147
1
太多了, 可以本人写, 接分,祝好运