在Log4Qt中存在一个比较大的问题,当使用 DailyRollingFileAppender对日志进行输出时,会无限输出文件,也就是说,当系统运行很久时,日志文件有可能很大,大到无法想象。因此,很多开发者希望在DailyRollingFileAppender中加一个属性,用于配置日志文件的个数。
但是如何做呢?
在Java语言中,我找到一个实例,但是在QT中,没能找到,因此,只能通过自己看源代码,分析从而进行改进。
主要代码如下:
dailyrollingfileappender.h:
class DailyRollingFileAppender : public FileAppender
{
Q_OBJECT /*!
* The property holds the date pattern used by the appender.
*
* The default is DAILY_ROLLOVER for rollover at midnight each day.
*
* \sa datePattern(), setDatePattern()
*/
Q_PROPERTY(QString datePattern READ datePattern WRITE setDatePattern) /*!
* The property holds the maximum backup count used by the appender.
*
* The default is 1.
*
* \sa maxBackupIndex(), setMaxBackupIndex()
*/
Q_PROPERTY(int maxBackupIndex READ maxBackupIndex WRITE setMaxBackupIndex) public:
/*!
* The enum DatePattern defines constants for date patterns.
*
* \sa setDatePattern(DatePattern)
*/
enum DatePattern
{
/*! The minutely date pattern string is "'.'yyyy-MM-dd-hh-mm". */
MINUTELY_ROLLOVER = ,
/*! The hourly date pattern string is "'.'yyyy-MM-dd-hh". */
HOURLY_ROLLOVER,
/*! The half-daily date pattern string is "'.'yyyy-MM-dd-a". */
HALFDAILY_ROLLOVER,
/*! The daily date pattern string is "'.'yyyy-MM-dd". */
DAILY_ROLLOVER,
/*! The weekly date pattern string is "'.'yyyy-ww". */
WEEKLY_ROLLOVER,
/*! The monthly date pattern string is "'.'yyyy-MM". */
MONTHLY_ROLLOVER
};
Q_ENUMS(DatePattern) DailyRollingFileAppender(QObject *pParent = );
DailyRollingFileAppender(Layout *pLayout,
const QString &rFileName,
const QString &rDatePattern,
const int rmaxBackupIndex = ,
QObject *pParent = );
virtual ~DailyRollingFileAppender(); private:
DailyRollingFileAppender(const DailyRollingFileAppender &rOther); // Not implemented
DailyRollingFileAppender &operator=(const DailyRollingFileAppender &rOther); // Not implemented void removeFiles(); public:
int maxBackupIndex() const;
void setMaxBackupIndex(int maxBackupIndex);
QString datePattern() const; /*!
* Sets the datePattern to the value specified by the \a datePattern
* constant.
*/
void setDatePattern(DatePattern datePattern); void setDatePattern(const QString &rDatePattern); virtual void activateOptions(); protected:
virtual void append(const LoggingEvent &rEvent); /*!
* Tests if all entry conditions for using append() in this class are
* met.
*
* If a conditions is not met, an error is logged and the function
* returns false. Otherwise the result of
* FileAppender::checkEntryConditions() is returned.
*
* The checked conditions are:
* - A valid pattern has been set (APPENDER_USE_INVALID_PATTERN_ERROR)
*
* The function is called as part of the checkEntryConditions() chain
* started by AppenderSkeleton::doAppend().
*
* \sa AppenderSkeleton::doAppend(),
* AppenderSkeleton::checkEntryConditions()
*/
virtual bool checkEntryConditions() const; protected:
#ifndef QT_NO_DEBUG_STREAM
/*!
* Writes all object member variables to the given debug stream
* \a rDebug and returns the stream.
*
* <tt>
* %DailyRollingFileAppender(name:"DRFA" activedatepattern:"'.'yyyy-MM-dd-hh-mm"
* appendfile:false bufferedio:true
* datepattern:"'.'yyyy-MM-dd-hh-mm"
* encoding:"" frequency:"MINUTELY_ROLLOVER"
* file:"/log.txt" filter:0x0 immediateflush:true
* isactive:true isclosed:false layout:"TTCC"
* referencecount:1
* rollovertime:QDateTime("Mon Oct 22 05:23:00 2007")
* threshold: "NULL" writer: 0x0 )
* </tt>
* \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject)
*/
virtual QDebug debug(QDebug &rDebug) const;
#endif // QT_NO_DEBUG_STREAM private:
void computeFrequency();
void computeRollOverTime();
QString frequencyToString() const;
void rollOver(); private:
QString mDatePattern;
DatePattern mFrequency;
QString mActiveDatePattern;
QDateTime mRollOverTime;
QString mRollOverSuffix; protected:
int mMaxBackupIndex;
}; /**************************************************************************
* Operators, Helper
**************************************************************************/ /**************************************************************************
* Inline
**************************************************************************/ inline QString DailyRollingFileAppender::datePattern() const
{ QMutexLocker locker(&mObjectGuard);
return mDatePattern; } inline void DailyRollingFileAppender::setDatePattern(const QString &rDatePattern)
{ QMutexLocker locker(&mObjectGuard);
mDatePattern = rDatePattern; } inline int DailyRollingFileAppender::maxBackupIndex() const
{ QMutexLocker locker(&mObjectGuard);
return mMaxBackupIndex; } inline void DailyRollingFileAppender::setMaxBackupIndex(int maxBackupIndex)
{ QMutexLocker locker(&mObjectGuard);
mMaxBackupIndex = maxBackupIndex; }
其中,Q_PROPERTY(int maxBackupIndex READ maxBackupIndex WRITE setMaxBackupIndex)这句话什么重要。
dailyrollingfileappender.cpp:
DailyRollingFileAppender::DailyRollingFileAppender(QObject *pParent) :
FileAppender(pParent),
mDatePattern()
{
setDatePattern(DAILY_ROLLOVER);
} DailyRollingFileAppender::DailyRollingFileAppender(Layout *pLayout,
const QString &rFileName,
const QString &rDatePattern,
const int rmaxBackupIndex,
QObject *pParent) :
FileAppender(pLayout, rFileName, pParent),
mDatePattern(), mMaxBackupIndex(rmaxBackupIndex)
{
setDatePattern(rDatePattern);
} DailyRollingFileAppender::~DailyRollingFileAppender()
{
close();
} void DailyRollingFileAppender::setDatePattern(DatePattern datePattern)
{
switch (datePattern)
{
case MINUTELY_ROLLOVER:
setDatePattern(QLatin1String("'.'yyyy-MM-dd-hh-mm"));
break;
case HOURLY_ROLLOVER:
setDatePattern(QLatin1String("'.'yyyy-MM-dd-hh"));
break;
case HALFDAILY_ROLLOVER:
setDatePattern(QLatin1String("'.'yyyy-MM-dd-a"));
break;
case DAILY_ROLLOVER:
setDatePattern(QLatin1String("'.'yyyy-MM-dd"));
break;
case WEEKLY_ROLLOVER:
setDatePattern(QLatin1String("'.'yyyy-ww"));
break;
case MONTHLY_ROLLOVER:
setDatePattern(QLatin1String("'.'yyyy-MM"));
break;
default:
Q_ASSERT_X(false, "DailyRollingFileAppender::setDatePattern()", "Invalid datePattern constant");
setDatePattern(DAILY_ROLLOVER);
};
} void DailyRollingFileAppender::activateOptions()
{
QMutexLocker locker(&mObjectGuard); computeFrequency();
if (!mActiveDatePattern.isEmpty())
{
computeRollOverTime();
FileAppender::activateOptions();
}
} void DailyRollingFileAppender::append(const LoggingEvent &rEvent)
{
// Q_ASSERT_X(, "DailyRollingFileAppender::append()", "Lock must be held by caller") if (QDateTime::currentDateTime() > mRollOverTime)
rollOver();
FileAppender::append(rEvent);
} bool DailyRollingFileAppender::checkEntryConditions() const
{
// Q_ASSERT_X(, "DailyRollingFileAppender::checkEntryConditions()", "Lock must be held by caller") if (mActiveDatePattern.isEmpty())
{
LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Use of appender '%1' without having a valid date pattern set"),
APPENDER_USE_INVALID_PATTERN_ERROR);
e << name();
logger()->error(e);
return false;
} return FileAppender::checkEntryConditions();
} #ifndef QT_NO_DEBUG_STREAM
QDebug DailyRollingFileAppender::debug(QDebug &rDebug) const
{
QString layout_name;
if (layout())
layout_name = layout()->name();
QString codec_name;
if (encoding())
codec_name = QLatin1String(encoding()->name()); rDebug.nospace() << "DailyRollingFileAppender("
<< "name:" << name() << " "
<< "activedatepattern:" << mActiveDatePattern << " "
<< "appendfile:" << appendFile() << " "
<< "bufferedio:" << bufferedIo() << " "
<< "datepattern:" << datePattern() << " "
<< "encoding:" << codec_name << " "
<< "frequency:" << frequencyToString() << " "
<< "file:" << file() << " "
<< "filter:" << firstFilter() << " "
<< "immediateflush:" << immediateFlush() << " "
<< "isactive:" << isActive() << " "
<< "isclosed:" << isClosed() << " "
<< "layout:" << layout_name << " "
<< "referencecount:" << referenceCount() << " "
<< "rollovertime:" << mRollOverTime
<< "threshold:" << threshold().toString()
<< "writer:" << writer()
<< ")";
return rDebug.space();
}
#endif // QT_NO_DEBUG_STREAM void DailyRollingFileAppender::computeFrequency()
{
// Q_ASSERT_X(, "DailyRollingFileAppender::computeFrequency()", "Lock must be held by caller") const DateTime start_time(QDate(, , ), QTime(, ));
const QString start_string = start_time.toString(mDatePattern);
mActiveDatePattern.clear(); if (start_string != static_cast<DateTime>(start_time.addSecs()).toString(mDatePattern))
mFrequency = MINUTELY_ROLLOVER;
else if (start_string != static_cast<DateTime>(start_time.addSecs( * )).toString(mDatePattern))
mFrequency = HOURLY_ROLLOVER;
else if (start_string != static_cast<DateTime>(start_time.addSecs( * * )).toString(mDatePattern))
mFrequency = HALFDAILY_ROLLOVER;
else if (start_string != static_cast<DateTime>(start_time.addDays()).toString(mDatePattern))
mFrequency = DAILY_ROLLOVER;
else if (start_string != static_cast<DateTime>(start_time.addDays()).toString(mDatePattern))
mFrequency = WEEKLY_ROLLOVER;
else if (start_string != static_cast<DateTime>(start_time.addMonths()).toString(mDatePattern))
mFrequency = MONTHLY_ROLLOVER;
else
{
LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("The pattern '%1' does not specify a frequency for appender '%2'"),
APPENDER_INVALID_PATTERN_ERROR);
e << mDatePattern << name();
logger()->error(e);
return;
} mActiveDatePattern = mDatePattern;
logger()->trace("Frequency set to %2 using date pattern %1",
mActiveDatePattern,
frequencyToString());
} void DailyRollingFileAppender::computeRollOverTime()
{
// Q_ASSERT_X(, "DailyRollingFileAppender::computeRollOverTime()", "Lock must be held by caller")
Q_ASSERT_X(!mActiveDatePattern.isEmpty(), "DailyRollingFileAppender::computeRollOverTime()", "No active date pattern"); QDateTime now = QDateTime::currentDateTime();
QDate now_date = now.date();
QTime now_time = now.time();
QDateTime start; switch (mFrequency)
{
case MINUTELY_ROLLOVER:
{
start = QDateTime(now_date,
QTime(now_time.hour(),
now_time.minute(),
, ));
mRollOverTime = start.addSecs();
}
break;
case HOURLY_ROLLOVER:
{
start = QDateTime(now_date,
QTime(now_time.hour(),
, , ));
mRollOverTime = start.addSecs(*);
}
break;
case HALFDAILY_ROLLOVER:
{
int hour = now_time.hour();
if (hour >= )
hour = ;
else
hour = ;
start = QDateTime(now_date,
QTime(hour, , , ));
mRollOverTime = start.addSecs(**);
}
break;
case DAILY_ROLLOVER:
{
start = QDateTime(now_date,
QTime(, , , ));
mRollOverTime = start.addDays();
}
break;
case WEEKLY_ROLLOVER:
{
// QT numbers the week days 1..7. The week starts on Monday.
// Change it to being numbered 0..6, starting with Sunday.
int day = now_date.dayOfWeek();
if (day == Qt::Sunday)
day = ;
start = QDateTime(now_date,
QTime(, , , )).addDays(- * day);
mRollOverTime = start.addDays();
}
break;
case MONTHLY_ROLLOVER:
{
start = QDateTime(QDate(now_date.year(),
now_date.month(),
),
QTime(, , , ));
mRollOverTime = start.addMonths();
}
break;
default:
Q_ASSERT_X(false, "DailyRollingFileAppender::computeInterval()", "Invalid datePattern constant");
mRollOverTime = QDateTime::fromTime_t();
} mRollOverSuffix = static_cast<DateTime>(start).toString(mActiveDatePattern);
Q_ASSERT_X(static_cast<DateTime>(now).toString(mActiveDatePattern) == mRollOverSuffix,
"DailyRollingFileAppender::computeRollOverTime()", "File name changes within interval");
Q_ASSERT_X(mRollOverSuffix != static_cast<DateTime>(mRollOverTime).toString(mActiveDatePattern),
"DailyRollingFileAppender::computeRollOverTime()", "File name does not change with rollover"); logger()->trace("Computing roll over time from %1: The interval start time is %2. The roll over time is %3",
now,
start,
mRollOverTime);
} QString DailyRollingFileAppender::frequencyToString() const
{
QMetaEnum meta_enum = metaObject()->enumerator(metaObject()->indexOfEnumerator("DatePattern"));
return QLatin1String(meta_enum.valueToKey(mFrequency));
} void DailyRollingFileAppender::removeFiles()
{
QDir dir("./logs");
dir.setFilter(QDir::Files | QDir::Hidden | QDir::NoSymLinks);
dir.setSorting(QDir::Time | QDir::Reversed); QFileInfoList list = dir.entryInfoList();
QFileInfo fileInfo; if(list.size() >= mMaxBackupIndex)
{
int index = ;
int diff = list.size() - mMaxBackupIndex;
for (int i = ; i < list.size(); ++i)
{
fileInfo = list.at(i);
if(index >= diff)
{
break;
} QFile file(fileInfo.absoluteFilePath());
QByteArray ba = fileInfo.absoluteFilePath().toLatin1();
cout<<ba.data()<<endl;
file.remove();
index++;
} }
} void DailyRollingFileAppender::rollOver()
{
// Q_ASSERT_X(, "DailyRollingFileAppender::rollOver()", "Lock must be held by caller")
Q_ASSERT_X(!mActiveDatePattern.isEmpty(), "DailyRollingFileAppender::rollOver()", "No active date pattern"); QString roll_over_suffix = mRollOverSuffix;
computeRollOverTime();
if (roll_over_suffix == mRollOverSuffix)
return; closeFile(); QString target_file_name = file() + roll_over_suffix;
QFile f(target_file_name);
if (f.exists() && !removeFile(f))
return;
f.setFileName(file());
if (!renameFile(f, target_file_name))
return;
openFile(); removeFiles();
//huabo }