📄 nlfileappender.cpp
字号:
/**
* 附加器附加类实现
* @file NLFileAppender.cpp
* @date 14-Jul-2005
* @author 胡春雨
* @version 1.0.0: 初始版本
*/
#include "nlkit/NLFileAppender.h"
#include <dirent.h>
#include <iostream>
#include <sstream>
#include <ctype.h>
#include <unistd.h>
#include <algorithm>
using namespace std;
#define MINIMUM_ROLLING_LOG_SIZE 200*1024L /**< 最小的循环文件大小定义 */
namespace nlkit
{
void rolloverFiles(const string& filename, unsigned int maxBackupIndex)
{
ostringstream buffer;
buffer << filename << "." << maxBackupIndex;
remove(buffer.str().c_str());
for (int i=maxBackupIndex - 1; i >= 1; i--)
{
ostringstream source;
ostringstream target;
source << filename << "." << i;
target << filename << "." << (i+1);
rename(source.str().c_str(), target.str().c_str());
}
}
NLFileAppender::NLFileAppender(const string& filename,
const char* type, bool immediateFlush, bool withAdorn)
: m_immediateFlush(immediateFlush), m_withAdorn(withAdorn)
{
init(filename, type);
}
void NLFileAppender::init(const string& filename, const char* type)
{
m_filename = filename;
m_out = fopen(filename.c_str(), type);
if (m_out == NULL)
{
getErrorHandler()->error("Unable to open file: " + filename);
return;
}
}
void NLFileAppender::reopen(const string& filename, const char* type)
{
fclose(m_out);
remove(m_filename.c_str());
m_out = fopen(filename.c_str(), type);
if (m_out == NULL)
{
getErrorHandler()->error("Unable to open file: " + filename);
return;
}
}
NLFileAppender::~NLFileAppender()
{
destructorImpl();
}
void NLFileAppender::close()
{
fclose(m_out);
m_out = NULL;
m_closed = true;
}
void NLFileAppender::append(const NLEvent& event)
{
if(m_out == NULL)
{
getErrorHandler()->error("appender's out is not opened");
return;
}
ostringstream os;
m_layout->format(os, event);
/*
if (m_withAdorn)
{
os << event.getTimestamp().getFormattedTime("%Y-%m-%d %H:%M:%S.%%q");
os << " [" << getpid() ;
if (NULL != event.getAdornHandle())
os << ":" << event.getAdornHandle()->message();
os << "] " << NLLogLevelName[event.getNLLogLevel()] << " - " << event.getMessage();
if (0 != event.getFile().size())
{
os << " [" << event.getFile() << ":" << event.getLine() << "]";
}
}
else
{
os << event.getMessage();
}
os << endl;*/
fprintf(m_out, "%s", os.str().c_str());
if (m_immediateFlush)
{
fflush(m_out);
}
}
NLRollingFileAppender::NLRollingFileAppender(const string& filename,
long long maxFileSize,
int maxBackupIndex,
bool immediateFlush,
bool withAdorn)
: NLFileAppender(filename, "a", immediateFlush, withAdorn)
{
init(maxFileSize, maxBackupIndex);
}
void NLRollingFileAppender::init(long long maxFileSize, int maxBackupIndex)
{
m_maxFileSize = maxFileSize > (long long)MINIMUM_ROLLING_LOG_SIZE ? maxFileSize : (long long)MINIMUM_ROLLING_LOG_SIZE;
m_maxBackupIndex = max(maxBackupIndex, 1);
}
NLRollingFileAppender::~NLRollingFileAppender()
{
destructorImpl();
}
void NLRollingFileAppender::append(const NLEvent& event)
{
if(m_out == NULL)
{
getErrorHandler()->error("appender's out is not opened");
return;
}
ostringstream os;
m_layout->format(os, event);
/*
if (m_withAdorn)
{
os << event.getTimestamp().getFormattedTime("%Y-%m-%d %H:%M:%S.%%q");
os << " [" << getpid() ;
if (NULL != event.getAdornHandle())
os << ":" << event.getAdornHandle()->message();
os << "] " << NLLogLevelName[event.getNLLogLevel()] << " - " << event.getMessage();
if (0 != event.getFile().size())
{
os << " [" << event.getFile() << ":" << event.getLine() << "]";
}
}
else
{
os << event.getMessage();
}
os << endl;
*/
fprintf(m_out, "%s", os.str().c_str());
if (m_immediateFlush)
{
fflush(m_out);
}
if (ftell(m_out) > m_maxFileSize)
{
rollover();
}
}
void NLRollingFileAppender::rollover()
{
if (m_maxBackupIndex > 0)
{
rolloverFiles(m_filename, m_maxBackupIndex);
fclose(m_out);
string target = m_filename + ".1";
rename(m_filename.c_str(), target.c_str());
m_out = fopen(m_filename.c_str(), "a");
}
else
{
fclose(m_out);
m_out = fopen(m_filename.c_str(), "w");
}
}
NLDailyRollingFileAppender::NLDailyRollingFileAppender(const string& filename,
NLDailyRollingSchedule schedule,
bool immediateFlush,
int maxBackupIndex,
bool withAdorn)
: NLFileAppender(filename, "a", immediateFlush, withAdorn),
m_maxBackupIndex(maxBackupIndex)
{
init(schedule);
}
void NLDailyRollingFileAppender::init(NLDailyRollingSchedule schedule)
{
m_schedule = schedule;
NLTime now = NLTime::gettimeofday();
NLTime::setCalculateBeginTime(now, m_schedule);
m_scheduledFilename = getFilename(now);
m_nextRolloverTime = NLTime::calculateNextRolloverTime(now, m_schedule);
}
NLDailyRollingFileAppender::~NLDailyRollingFileAppender()
{
destructorImpl();
}
void NLDailyRollingFileAppender::close()
{
rollover();
NLFileAppender::close();
}
void NLDailyRollingFileAppender::append(const NLEvent& event)
{
if (m_out == NULL)
{
getErrorHandler()->error("file is not open: " + m_filename);
return;
}
if (NLTime::getCalculateBeginTime(event.getTimestamp(), m_schedule) >= m_nextRolloverTime)
{
rollover();
}
ostringstream os;
m_layout->format(os, event);
/*
if (m_withAdorn)
{
os << event.getTimestamp().getFormattedTime("%Y-%m-%d %H:%M:%S.%%q");
os << " [" << getpid() ;
if (NULL != event.getAdornHandle())
os << ":" << event.getAdornHandle()->message();
os << "] " << NLLogLevelName[event.getNLLogLevel()] << " - " << event.getMessage();
if (0 != event.getFile().size())
{
os << " [" << event.getFile() << ":" << event.getLine() << "]";
}
}
else
{
os << event.getMessage();
}
os << endl;*/
fprintf(m_out, "%s", os.str().c_str());
if (m_immediateFlush)
{
fflush(m_out);
}
}
void NLDailyRollingFileAppender::rollover()
{
fclose(m_out);
rolloverFiles(m_scheduledFilename, m_maxBackupIndex);
ostringstream backupTarget;
backupTarget << m_scheduledFilename << "." << 1;
rename(m_scheduledFilename.c_str(), backupTarget.str().c_str());
rename(m_filename.c_str(), m_scheduledFilename.c_str());
m_out = fopen(m_filename.c_str(), "a");
NLTime now = NLTime::gettimeofday();
for (; now >= m_nextRolloverTime; )
{
m_nextRolloverTime = NLTime::calculateNextRolloverTime(m_nextRolloverTime, m_schedule);
}
m_nextRolloverTime = NLTime::calculateNextRolloverTime(m_nextRolloverTime, m_schedule, -1);
m_scheduledFilename = getFilename(m_nextRolloverTime);
}
string NLDailyRollingFileAppender::getFilename(const NLTime& t) const
{
string pattern;
switch (m_schedule)
{
case MONTHLY:
pattern = "%Y-%m";
break;
case WEEKLY:
pattern = "%Y-%W";
break;
case DAILY:
pattern = "%Y-%m-%d";
break;
case TWICE_DAILY:
pattern = "%Y-%m-%d-%p";
break;
case HOURLY:
pattern = "%Y-%m-%d-%H";
break;
case MINUTELY:
pattern = "%Y-%m-%d-%H-%M";
break;
};
return m_filename + "." + t.getFormattedTime(pattern, false);
}
NLParallelFileAppender::NLParallelFileAppender(const string& filename,
NLDailyRollingSchedule schedule,
bool immediateFlush,
long long maxFileSize,
int maxBackupIndex,
bool withAdorn)
: NLDailyRollingFileAppender(filename, schedule, immediateFlush, maxBackupIndex, withAdorn),
m_maxFileSize(maxFileSize),
m_curIdx(0)
{
init();
}
NLParallelFileAppender::~NLParallelFileAppender()
{
destructorImpl();
}
void NLParallelFileAppender::close()
{
rollover(CLOSE_SWITCH);
NLFileAppender::close();
}
void NLParallelFileAppender::rollover(switchtype type)
{
fclose(m_out);
switch (type)
{
case SIZE_SWITCH:
// case CLOSE_SWITCH:
{
ostringstream newTarget;
newTarget << m_scheduledFilename << "." << ++m_curIdx;
m_out = ::fopen(newTarget.str().c_str(), "a");
}
break;
case TIME_SWITCH:
{
NLTime now = NLTime::gettimeofday();
for (; now >= m_nextRolloverTime; )
{
m_nextRolloverTime = NLTime::calculateNextRolloverTime(m_nextRolloverTime, m_schedule);
}
//date:2006.3.24
//delete by mzh
//下面的语句多减去了1个m_schedule的数值,那样m_nextRolloverTime就<=now,就会一直触发时间切换
//m_nextRolloverTime = NLTime::calculateNextRolloverTime(m_nextRolloverTime, m_schedule, -1);
//date:2006.3.29
//modify by mzh,文件名称格式应取当前时间
m_scheduledFilename = getFilename(now);
m_out = ::fopen(m_scheduledFilename.c_str(), "a");
m_curIdx = 0;
}
break;
}
}
void NLParallelFileAppender::append(const NLEvent& event)
{
if(m_out == NULL)
{
getErrorHandler()->error("file is not open: " + m_filename);
return;
}
if (NLTime::getCalculateBeginTime(event.getTimestamp(), m_schedule) >= m_nextRolloverTime)
{
rollover(TIME_SWITCH);
}
ostringstream os;
m_layout->format(os, event);
/*
if (m_withAdorn)
{
if (m_schedule < DAILY) //日志切换周期大于一天,在日志中显示日期
os << event.getTimestamp().getFormattedTime("%Y-%m-%d %H:%M:%S.%%q");
else
os << event.getTimestamp().getFormattedTime("%H:%M:%S.%%Q");
os << " [" << getpid() ;
if (NULL != event.getAdornHandle())
os << ":" << event.getAdornHandle()->message();
os << "] " << NLLogLevelName[event.getNLLogLevel()] << " - " << event.getMessage();
if (0 != event.getFile().size())
{
os << " [" << event.getFile() << ":" << event.getLine() << "]";
}
}
else
{
os << event.getMessage();
}
os << endl;*/
fprintf(m_out, "%s", os.str().c_str());
if (m_immediateFlush)
{
fflush(m_out);
}
if (ftell(m_out) > m_maxFileSize)
{
rollover(SIZE_SWITCH);
}
}
void NLParallelFileAppender::init()
{
m_curIdx = getCurIdx();
if (m_curIdx == 0)
reopen(m_scheduledFilename, "a");
else
{
ostringstream newTarget;
newTarget << m_scheduledFilename << "." << m_curIdx;
reopen(newTarget.str(), "a");
}
}
int NLParallelFileAppender::getCurIdx()
{
string dirname("");
string filename("");
size_t pos = m_scheduledFilename.rfind("/");
if (pos != string::npos)
{
dirname = m_scheduledFilename.substr(0, pos);
filename = m_scheduledFilename.substr(pos+1, m_scheduledFilename.size()-pos);
}
else
{
dirname = "./";
filename = m_scheduledFilename;
}
DIR* dirp = opendir(dirname.c_str());
struct dirent *dp;
int idx = 0;
while ((dp = readdir(dirp)) != NULL)
{
char *ptr;
if ((ptr = strstr(dp->d_name, filename.c_str())) != NULL && strlen(dp->d_name) != filename.size())
{
char tmp[20]; bool bFlag = true;
snprintf(tmp, sizeof(tmp), "%s", ptr+filename.size()+1);
for (int i=0; i<strlen(tmp); ++i)
{
if (isdigit(tmp[i]) == 0)
{
bFlag = false;
break;
}
}
if (bFlag)
idx = max(idx, atoi(tmp));
}
}
closedir(dirp);
return idx;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -