续:“改进log4net支持按日期产生日志文件”
上篇的随笔我看了大家的评论,感觉有种罪过的感觉,因为由于自己的误判而误导了许多对log4net不太熟悉的朋友,在这里我表示道歉,虽然只是自己的随笔,但我却怕误人子弟。
其实RollingFileAppender的功能并不完美,我在上一篇的评论中也提到,使用RollingFileAppender产生日期文件名有可能慢半拍,因为这是我测试出来的,但是什么原因导致的呢?我用了一下午的时间去看了RollingFileAppender的代码,结果发现,它的日期只能是递增的,也就是说,假如产生了log20060420.log的日志文件的话,如果由于某种原因,系统的时间是2006-04-18时,它不会生成log20060418.log文件,它会把18号的日志记到log20060420.log文件里。刚才说的产生日期文件名有可能慢半拍只是表面,而其原因就在于此,所以当系统的时间从2006-4-20设置为2006-4-18,再设置为2006-4-21时,只会生成两个日志文件,log20060420.log和log20060421.log,也许这并不算啥,但这就违背了按照日期来产生日志文件的初衷,也许很多人都觉得着没啥,但使用log4net的系统有很多,如果你的系统要求的日志比较严格的话,这无疑是个缺陷,假如有人把系统的时间改为以前的某个时间,然后对系统做了一些手脚(搞破坏),管理员通过看日志文件名就会感觉不对劲,而RollingFileAppender并没有做到这一点,所以我对它进行了改进。在这里,我想说一下上一篇中对log4net的改进,说实话,很糟糕,虽然功能上实现了自己需要的功能,却破坏了其本来完整的体系,极有可能带来代码地震,所以,我要说上一篇的改进很不理智的,希望不要误导刚使用log4net的朋友。
接下来,我已经把RollingFileAppender修改了一下,使它的日期文件名不局限于递增的,真正达到按照日期来产生日志文件的目的。首先,我想说一下,原始的RollingFileAppender是怎么产生按照日期的日志文件名的。首先,你的配置文件要是这样的:
我的修改很简单,就是把比较的方法改一下,如果不属于同一个日期范围内的,就产生新的日志文件。
代码修改仅在RollingFileAppender里,步骤如下:
1)增加比较的方法:
2)修改方法ActivateOptions() 的代码,把m_nextCheck = NextCheckDate(m_now, m_rollPoint);改为:m_nextCheck = m_now;
3)修改方法Append的代码:把原来的代码
改为:
4)修改方法:RollOverTime把SafeOpenFile(m_baseFileName, false);改为SafeOpenFile(m_baseFileName, true);作用:使文件支持追加。
这样就修改结束了。原来的问题就不存在了。下面有一些感想,想顺便说一下,说实在的,在这里写随笔,感觉有很大的压力,怕误导别人是最担心的,电影《霍元甲》里有句经典的话:在台下只是看个热闹,而台上确实生死相搏。不知道你是否也深有同感?!欢迎大家批评指正!
其实RollingFileAppender的功能并不完美,我在上一篇的评论中也提到,使用RollingFileAppender产生日期文件名有可能慢半拍,因为这是我测试出来的,但是什么原因导致的呢?我用了一下午的时间去看了RollingFileAppender的代码,结果发现,它的日期只能是递增的,也就是说,假如产生了log20060420.log的日志文件的话,如果由于某种原因,系统的时间是2006-04-18时,它不会生成log20060418.log文件,它会把18号的日志记到log20060420.log文件里。刚才说的产生日期文件名有可能慢半拍只是表面,而其原因就在于此,所以当系统的时间从2006-4-20设置为2006-4-18,再设置为2006-4-21时,只会生成两个日志文件,log20060420.log和log20060421.log,也许这并不算啥,但这就违背了按照日期来产生日志文件的初衷,也许很多人都觉得着没啥,但使用log4net的系统有很多,如果你的系统要求的日志比较严格的话,这无疑是个缺陷,假如有人把系统的时间改为以前的某个时间,然后对系统做了一些手脚(搞破坏),管理员通过看日志文件名就会感觉不对劲,而RollingFileAppender并没有做到这一点,所以我对它进行了改进。在这里,我想说一下上一篇中对log4net的改进,说实话,很糟糕,虽然功能上实现了自己需要的功能,却破坏了其本来完整的体系,极有可能带来代码地震,所以,我要说上一篇的改进很不理智的,希望不要误导刚使用log4net的朋友。
接下来,我已经把RollingFileAppender修改了一下,使它的日期文件名不局限于递增的,真正达到按照日期来产生日志文件的目的。首先,我想说一下,原始的RollingFileAppender是怎么产生按照日期的日志文件名的。首先,你的配置文件要是这样的:
<appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
<param name="File" value="Log"/>
<param name="AppendToFile" value="true"/>
<param name="MaxSizeRollBackups" value="10"/>
<param name="StaticLogFileName" value="false"/>
<param name="DatePattern" value="yyyyMMdd".log""/>
<param name="RollingStyle" value="Date"/>
<layout type="log4net.Layout.PatternLayout">
<param name="ConversionPattern" value="%d [%t] %-5p %c [%x] - %m%n%n"/>
</layout>
</appender>
这样,log4net会根据配置文件读取相应的信息,DataPattern属性是一个日期模式字符窜,RollingFileAppender就是根据这个日期模式字符窜来计算你要以何种方式产生日期文件名,是以分钟为单位,还是小时,还是半天,天,一周,一月(方法为:ComputeCheckPeriod)。接下来,它会根据你产生日志文件的方式计算下一次产生日志文件的时间,然后,每次记录日志时就比较当前时间是否大于或等于下一次产生日志文件的时间,依此来决定是否产生新的日志文件.(看方法:Append)<param name="File" value="Log"/>
<param name="AppendToFile" value="true"/>
<param name="MaxSizeRollBackups" value="10"/>
<param name="StaticLogFileName" value="false"/>
<param name="DatePattern" value="yyyyMMdd".log""/>
<param name="RollingStyle" value="Date"/>
<layout type="log4net.Layout.PatternLayout">
<param name="ConversionPattern" value="%d [%t] %-5p %c [%x] - %m%n%n"/>
</layout>
</appender>
我的修改很简单,就是把比较的方法改一下,如果不属于同一个日期范围内的,就产生新的日志文件。
代码修改仅在RollingFileAppender里,步骤如下:
1)增加比较的方法:
/// <summary>
/// 根据日期比较是否日志文件名是否已经过期
/// </summary>
/// <param name="dtNow"></param>
/// <param name="dtLast"></param>
/// <returns></returns>
private bool IsLogFileExpire(DateTime dtNow,DateTime dtLast)
{
bool isExpire = false;
string strNow = dtNow.ToString(m_datePattern, System.Globalization.DateTimeFormatInfo.InvariantInfo);
string strLast = dtLast.ToString(m_datePattern, System.Globalization.DateTimeFormatInfo.InvariantInfo);
isExpire = string.Compare(strNow,strLast)==0? true:false;
return isExpire;
}
/// 根据日期比较是否日志文件名是否已经过期
/// </summary>
/// <param name="dtNow"></param>
/// <param name="dtLast"></param>
/// <returns></returns>
private bool IsLogFileExpire(DateTime dtNow,DateTime dtLast)
{
bool isExpire = false;
string strNow = dtNow.ToString(m_datePattern, System.Globalization.DateTimeFormatInfo.InvariantInfo);
string strLast = dtLast.ToString(m_datePattern, System.Globalization.DateTimeFormatInfo.InvariantInfo);
isExpire = string.Compare(strNow,strLast)==0? true:false;
return isExpire;
}
2)修改方法ActivateOptions() 的代码,把m_nextCheck = NextCheckDate(m_now, m_rollPoint);改为:m_nextCheck = m_now;
3)修改方法Append的代码:把原来的代码
if (m_rollDate)
{
DateTime n = m_dateTime.Now;
if (n >= m_nextCheck)
{
m_now = n;
m_nextCheck = NextCheckDate(m_now, m_rollPoint);
RollOverTime(true);
}
}
{
DateTime n = m_dateTime.Now;
if (n >= m_nextCheck)
{
m_now = n;
m_nextCheck = NextCheckDate(m_now, m_rollPoint);
RollOverTime(true);
}
}
改为:
if (m_rollDate)
{
DateTime n = m_dateTime.Now;
if(!this.IsLogFileExpire(n,m_nextCheck))
{
m_now = n;
m_nextCheck = m_now;
RollOverTime(true);
}
}
{
DateTime n = m_dateTime.Now;
if(!this.IsLogFileExpire(n,m_nextCheck))
{
m_now = n;
m_nextCheck = m_now;
RollOverTime(true);
}
}
4)修改方法:RollOverTime把SafeOpenFile(m_baseFileName, false);改为SafeOpenFile(m_baseFileName, true);作用:使文件支持追加。
这样就修改结束了。原来的问题就不存在了。下面有一些感想,想顺便说一下,说实在的,在这里写随笔,感觉有很大的压力,怕误导别人是最担心的,电影《霍元甲》里有句经典的话:在台下只是看个热闹,而台上确实生死相搏。不知道你是否也深有同感?!欢迎大家批评指正!