其他分享
首页 > 其他分享> > log4cxx增加时间回滚模式写maxBackUpIndex属性

log4cxx增加时间回滚模式写maxBackUpIndex属性

作者:互联网

在使用日志功能时,选择了目前比较常见的log4cxx,配置过程完全按照部分网上的经验进行配置。后续在使用过程中发现,配置的maxBackUpIndex属性并未生效,日志文件的数量还是在不停的增加。

使用的日志生成模式是DailyRollingFileAppender。

解决此问题时,摒弃了网上的经验,通过阅读源码发现。

log4cxx 日志新增模式有两种:

一种是按照文件大小生成:RollingFileAppender,此模式下,日志按照文件大小新增,日志文件大小在达到设定的阈值后会进行回滚,生成新文件,并且maxBackUpIndex属性正常生效,即日志文件数量达到设定的阈值后会自动进行删除,使日志文件始终保存在设定的阈值范围之内。

另一种是按照日期生成:DailyRollingFileAppender,此模式下,日志文件按照生成的配置生成文件,并且该模式下并没有maxBackUpIndex属性,即不会维护日志文件的数量。

鉴于此原因,对源码进行修改,增加类似RollingFileAppender模式下maxBackUpIndex属性,进行日志文件的管理,新增属性,maxBackUpDay,保持日志文件的数量为设定的天数之内的文件,超过次天数的日志在自动回滚时进行删除。

代码比较简单,模仿maxBackUpIndex属性的实现。

在dailyrollingfileappender.h文件中,新增成员变量:maxBackupDay

class LOG4CXX_EXPORT DailyRollingFileAppender : public log4cxx::rolling::RollingFileAppenderSkeleton {

private:
	int maxBackupDay;   //表示保留至少该天数之内的文件
};

在dailyrollingfileappender.cpp文件中,首先进行变量的初始化。

DailyRollingFileAppender::DailyRollingFileAppender() :
	maxBackupDay(0)
{
}

然后从配置文件中读取配置数据:

void DailyRollingFileAppender::setOption(const LogString& option,
   const LogString& value) {
     if (StringHelper::equalsIgnoreCase(option,
                     LOG4CXX_STR("DATEPATTERN"), LOG4CXX_STR("datepattern"))) 
	 {
             setDatePattern(value);
     } 
	 else if (StringHelper::equalsIgnoreCase(option,
		 LOG4CXX_STR("MAXBACKUPDAY"), LOG4CXX_STR("maxbackupday"))
		 || StringHelper::equalsIgnoreCase(option,
		 LOG4CXX_STR("MAXIMUMBACKUPDAY"), LOG4CXX_STR("maximumbackupday")))
	 {
		 maxBackupDay = StringHelper::toInt(value);     //读取配置文件的配置
	 }
	 else {
         RollingFileAppenderSkeleton::setOption(option, value);
     }
}

然后在设置回滚策略时设置该参数:

void DailyRollingFileAppender::activateOptions(log4cxx::helpers::Pool& pool) {
  
  policy->setFileNamePattern(pattern);
  policy->setMaxDay(maxBackupDay);
  policy->activateOptions(pool);
  setTriggeringPolicy(policy);
  setRollingPolicy(policy);

  RollingFileAppenderSkeleton::activateOptions(pool);
}

在基于时间的回滚策略中,进行该配置的处理与实现。

在timebasedrollingpolicy.h文件中,新增成员函数:

class LOG4CXX_EXPORT TimeBasedRollingPolicy : public RollingPolicyBase, public TriggeringPolicy 
{
private:
    int maxBackupDay;

    void deleteOldFiles(const LogString& currentActiveFile, log4cxx::helpers::Pool& pool);
    LogString extractFileDir(const LogString& In);  //获取当前日志目录
    LogString extractFileName(const LogString& In); //获取当前正在记录的日志文件名称

public:
        void setMaxDay(int newVal);   
};

在timebasedrollingpolicy.cpp文件中,实现文件的回滚删除。

void TimeBasedRollingPolicy::setMaxDay(int newVal)
{
	maxBackupDay = newVal;
}
LogString TimeBasedRollingPolicy::extractFileDir(const LogString& In)
{
	LogString strtemp = In;

	for (int i = strtemp.size() - 1; i >= 0; i--)
	{
		if (strtemp[i] == L'\\' || strtemp[i] == L'/')
		{
			strtemp.erase(i + 1);
			return(strtemp);
		}
	}

	return (L"");
}
LogString TimeBasedRollingPolicy::extractFileName(const LogString& In)
{
	const LogString& strtemp = In;

	for (int i = strtemp.size() - 1; i >= 0; i--)
	{
		if (strtemp[i] == L'\\' || strtemp[i] == L'/')
		{
			return strtemp.substr(i + 1);
		}
	}

	return(strtemp);
}
oid TimeBasedRollingPolicy::deleteOldFiles(const LogString& currentActiveFile, log4cxx::helpers::Pool& pool)
{
	if (maxBackupDay <= 0)
	{
		return;
	}

	if (currentActiveFile.size() == 0)
	{
		return;
	}

	LogString curLogFileDir = extractFileDir(currentActiveFile);    //获取到当前日志的目录
	LogString curLogFileName = extractFileName(currentActiveFile);  //获取到当前日志文件名


    /**获取到当前日志目录下面的所有文件列表,起初自己写了比较挫的使用WINAPI获取的代码,后面发现工程中已经有了比较简单的获取方法**/

	File toRenameBase;
	toRenameBase.setPath(curLogFileDir);
	std::vector<LogString> filename;
	std::vector<LogString> aryDelFiles;
	filename = toRenameBase.list(pool);

	__int64 sec1 = time(NULL);

	logchar t[] = { '.'};
	logchar tm[] = { '..' };

    //遍历获取到的文件列表,将最后一次修改时间与当前比较,时间差大于设置的天数的文件路径存入待删除的容器中,然后删除。

	for (int nIndex = 0; nIndex < filename.size(); ++nIndex)
	{
		if (filename[nIndex] == LogString(t) || filename[nIndex] == LogString(tm) || filename[nIndex] == curLogFileName)
		{
			continue;
		}

		File file;
		file.setPath(curLogFileDir + filename[nIndex]);
		log4cxx_time_t time = file.lastModified(pool) / 1000000;
		if (sec1 - time > maxBackupDay * 24 * 3600)
		{
			aryDelFiles.push_back(curLogFileDir + filename[nIndex]);
		}
	}

	//删除文件
	for (int i = 0; i < aryDelFiles.size(); i++)
	{
		DeleteFileW(aryDelFiles[i].c_str());
	}
}

回滚函数中有一点是需要注意的,就是我们删除文件的函数调用位置,在调试的时候,发现有一些代码在单步调试的时候不执行。

RolloverDescriptionPtr TimeBasedRollingPolicy::rollover( const LogString& currentActiveFile, Pool& pool)
{
    ...
    LogString buf;
    ObjectPtr obj(new Date(n));
    formatFileName(obj, buf, pool);

    deleteOldFiles(currentActiveFile, pool);

    LogString newFileName(buf);

    //
    //  if file names haven't changed, no rollover
    //
    if (newFileName == lastFileName) {
    RolloverDescriptionPtr desc;
    return desc;
    }

    //  deleteOldFiles(currentActiveFile, pool);    调用放在此处时,发现单步调试时,不会被调用
    ...

    if (currentActiveFile != lastBaseName) {
    renameAction =
    new FileRenameAction(
    File().setPath(currentActiveFile), File().setPath(lastBaseName), true);
    nextActiveFile = currentActiveFile;
    }
    ...
}

道听途说,可能只是获取了一半的信息,另一半还在向你奔来的路上,你却直接转身返回了。找一找根源。更方便解决问题。站在系统的角度,而不是问题的角度。

标签:文件,maxBackUpIndex,currentActiveFile,回滚,LogString,strtemp,pool,日志,log4cxx
来源: https://blog.csdn.net/tax10240809163com/article/details/113053072