#pragma once
#include <string>
#include <deque>
#include "pthread.h"
enum Level
{
DEBUG = 1,
INFO = 2,
WARNING = 4,
ERROR = 8
};
class Logger : public ThreadWrapper
{
public:
Logger(int fileNum, int fileSize);
~Logger();
void WriteLog(Level level, char *fmt, ...);
virtual void Svc();
private:
char* m_logStr;
std::deque<std::string> m_logFileNameVec;
int m_totalSize;
int m_logLevel;
pthread_mutex_t* m_mutex;
pthread_cond_t* m_cond;
int m_fileSize;
int m_fileNum;
bool m_firstLog;
tm* m_startTime;
};
Logger::Logger(int fileNum, int fileSize, int logLevel)
:m_totalSize(0), m_logLevel(logLevel), m_fileSize(fileSize), m_fileNum(fileNum), m_firstLog(true)
{
m_logStr = new char[fileSize * 1.5];
memset(m_logStr, 0, sizeof(m_logStr));
pthread_mutex_init(m_mutex);
pthread_cond_init(m_cond);
}
Logger::~Logger()
{
if (m_logStr)
{
delete[] m_logStr;
m_logStr = 0;
}
pthread_mutex_destroy(m_mutex);
pthread_cond_destroy(m_cond);
}
void Logger::WriteLog(Level level, char *fmt, ...)
{
pthread_mutex_lock(m_mutex);
va_list args;
va_start (args, fmt);
m_totalSize += _vsnprintf(m_logStr + m_totalSize, fmt, args);
va_end (args);
if (m_firstLog)
{
time_t* t;
time(t);
m_startTime = localtime(t);
m_firstLog = false;
}
if (m_totalSize > m_fileSize)
{
pthread_cond_signal(m_cond);
}
pthread_mutex_unlock(m_mutex);
}
void Logger::Svc()
{
pthread_mutex_lock(m_mutex);
pthread_cond_wait(m_cond, m_mutex);
time_t* t;
time(t);
tm* curTime = localtime(t);
char fileName[50];
int n = strftime(fileName, 50,"%F %H:%M:%S-", m_startTime);
n += strftime(fileName + n, 50 - n,","%F %H:%M:%S", curTime);
fileName[n] = 0;
m_logFileNameVec.push_back(fileName);
if (m_logFileNameVec.size() > m_fileNum)
{
string delFileName = m_logFileNameVec[0];
m_logFileNameVec.pop_front();
unlink(delFileName);
}
FILE* outFile;
outFile = fopen(fileName, "w");
fwrite(m_logStr, m_totalSize, sizeof(char), outFile);
fclose(outFile);
m_totalSize = 0;
m_firstLog = true;
delete[] m_logStr;
m_logStr = new char[m_fileSize * 1.5];
memset(m_logStr, 0, sizeof(m_logStr));
pthread_mutex_unlock(m_mutex);
}
此Logger类的作用:
可以通过构造函数指定日志文件的数量和每个文件的大小,文件名以对应日志文件中记录的起始和终止时间命名,适合需长期运行的服务器程序使用。
优点:适用于多线程环境,执行效率高(文件内容先缓存,直到用户手动flush或达到预设的大小时才一次写出到文件)
缺点:文件数目只对当前进程有效,当进程频繁重启时,对之前已经存在的文件不作统计,会导致日志文件不断增多。