📄 rollingfileappender.cs
字号:
{
System.IO.File.Delete(fileToDelete);
}
LogLog.Debug("RollingFileAppender: Deleted file [" + fileName + "]");
}
catch(Exception deleteEx)
{
if (fileToDelete == fileName)
{
// Unable to move or delete the file
ErrorHandler.Error("Exception while deleting file [" + fileToDelete + "]", deleteEx, ErrorCode.GenericFailure);
}
else
{
// Moved the file, but the delete failed. File is probably locked.
// The file should automatically be deleted when the lock is released.
LogLog.Debug("RollingFileAppender: Exception while deleting temp file [" + fileToDelete + "]", deleteEx);
}
}
}
}
/// <summary>
/// Implements file roll base on file size.
/// </summary>
/// <remarks>
/// <para>
/// If the maximum number of size based backups is reached
/// (<c>curSizeRollBackups == maxSizeRollBackups</c>) then the oldest
/// file is deleted -- its index determined by the sign of countDirection.
/// If <c>countDirection</c> < 0, then files
/// {<c>File.1</c>, ..., <c>File.curSizeRollBackups -1</c>}
/// are renamed to {<c>File.2</c>, ...,
/// <c>File.curSizeRollBackups</c>}. Moreover, <c>File</c> is
/// renamed <c>File.1</c> and closed.
/// </para>
/// <para>
/// A new file is created to receive further log output.
/// </para>
/// <para>
/// If <c>maxSizeRollBackups</c> is equal to zero, then the
/// <c>File</c> is truncated with no backup files created.
/// </para>
/// <para>
/// If <c>maxSizeRollBackups</c> < 0, then <c>File</c> is
/// renamed if needed and no files are deleted.
/// </para>
/// </remarks>
protected void RollOverSize()
{
this.CloseFile(); // keep windows happy.
LogLog.Debug("RollingFileAppender: rolling over count ["+((CountingQuietTextWriter)QuietWriter).Count+"]");
LogLog.Debug("RollingFileAppender: maxSizeRollBackups ["+m_maxSizeRollBackups+"]");
LogLog.Debug("RollingFileAppender: curSizeRollBackups ["+m_curSizeRollBackups+"]");
LogLog.Debug("RollingFileAppender: countDirection ["+m_countDirection+"]");
RollOverRenameFiles(File);
if (!m_staticLogFileName && m_countDirection >= 0)
{
m_curSizeRollBackups++;
}
// This will also close the file. This is OK since multiple close operations are safe.
SafeOpenFile(m_baseFileName, false);
}
/// <summary>
/// Implements file roll.
/// </summary>
/// <param name="baseFileName">the base name to rename</param>
/// <remarks>
/// <para>
/// If the maximum number of size based backups is reached
/// (<c>curSizeRollBackups == maxSizeRollBackups</c>) then the oldest
/// file is deleted -- its index determined by the sign of countDirection.
/// If <c>countDirection</c> < 0, then files
/// {<c>File.1</c>, ..., <c>File.curSizeRollBackups -1</c>}
/// are renamed to {<c>File.2</c>, ...,
/// <c>File.curSizeRollBackups</c>}.
/// </para>
/// <para>
/// If <c>maxSizeRollBackups</c> is equal to zero, then the
/// <c>File</c> is truncated with no backup files created.
/// </para>
/// <para>
/// If <c>maxSizeRollBackups</c> < 0, then <c>File</c> is
/// renamed if needed and no files are deleted.
/// </para>
/// <para>
/// This is called by <see cref="RollOverSize"/> to rename the files.
/// </para>
/// </remarks>
protected void RollOverRenameFiles(string baseFileName)
{
// If maxBackups <= 0, then there is no file renaming to be done.
if (m_maxSizeRollBackups != 0)
{
if (m_countDirection < 0)
{
// Delete the oldest file, to keep Windows happy.
if (m_curSizeRollBackups == m_maxSizeRollBackups)
{
DeleteFile(baseFileName + '.' + m_maxSizeRollBackups);
m_curSizeRollBackups--;
}
// Map {(maxBackupIndex - 1), ..., 2, 1} to {maxBackupIndex, ..., 3, 2}
for (int i = m_curSizeRollBackups; i >= 1; i--)
{
RollFile((baseFileName + "." + i), (baseFileName + '.' + (i + 1)));
}
m_curSizeRollBackups++;
// Rename fileName to fileName.1
RollFile(baseFileName, baseFileName + ".1");
}
else
{
//countDirection >= 0
if (m_curSizeRollBackups >= m_maxSizeRollBackups && m_maxSizeRollBackups > 0)
{
//delete the first and keep counting up.
int oldestFileIndex = m_curSizeRollBackups - m_maxSizeRollBackups;
// If static then there is 1 file without a number, therefore 1 less archive
if (m_staticLogFileName)
{
oldestFileIndex++;
}
// If using a static log file then the base for the numbered sequence is the baseFileName passed in
// If not using a static log file then the baseFileName will already have a numbered postfix which
// we must remove, however it may have a date postfix which we must keep!
string archiveFileBaseName = baseFileName;
if (!m_staticLogFileName)
{
int lastDotIndex = archiveFileBaseName.LastIndexOf(".");
if (lastDotIndex >= 0)
{
archiveFileBaseName = archiveFileBaseName.Substring(0, lastDotIndex);
}
}
// Delete the archive file
DeleteFile(archiveFileBaseName + '.' + oldestFileIndex);
}
if (m_staticLogFileName)
{
m_curSizeRollBackups++;
RollFile(baseFileName, baseFileName + '.' + m_curSizeRollBackups);
}
}
}
}
#endregion
#region NextCheckDate
/// <summary>
/// Get the start time of the next window for the current rollpoint
/// </summary>
/// <param name="currentDateTime">the current date</param>
/// <param name="rollPoint">the type of roll point we are working with</param>
/// <returns>the start time for the next roll point an interval after the currentDateTime date</returns>
/// <remarks>
/// <para>
/// Returns the date of the next roll point after the currentDateTime date passed to the method.
/// </para>
/// <para>
/// The basic strategy is to subtract the time parts that are less significant
/// than the rollpoint from the current time. This should roll the time back to
/// the start of the time window for the current rollpoint. Then we add 1 window
/// worth of time and get the start time of the next window for the rollpoint.
/// </para>
/// </remarks>
protected DateTime NextCheckDate(DateTime currentDateTime, RollPoint rollPoint)
{
// Local variable to work on (this does not look very efficient)
DateTime current = currentDateTime;
// Do slightly different things depending on what the type of roll point we want.
switch(rollPoint)
{
case RollPoint.TopOfMinute:
current = current.AddMilliseconds(-current.Millisecond);
current = current.AddSeconds(-current.Second);
current = current.AddMinutes(1);
break;
case RollPoint.TopOfHour:
current = current.AddMilliseconds(-current.Millisecond);
current = current.AddSeconds(-current.Second);
current = current.AddMinutes(-current.Minute);
current = current.AddHours(1);
break;
case RollPoint.HalfDay:
current = current.AddMilliseconds(-current.Millisecond);
current = current.AddSeconds(-current.Second);
current = current.AddMinutes(-current.Minute);
if (current.Hour < 12)
{
current = current.AddHours(12 - current.Hour);
}
else
{
current = current.AddHours(-current.Hour);
current = current.AddDays(1);
}
break;
case RollPoint.TopOfDay:
current = current.AddMilliseconds(-current.Millisecond);
current = current.AddSeconds(-current.Second);
current = current.AddMinutes(-current.Minute);
current = current.AddHours(-current.Hour);
current = current.AddDays(1);
break;
case RollPoint.TopOfWeek:
current = current.AddMilliseconds(-current.Millisecond);
current = current.AddSeconds(-current.Second);
current = current.AddMinutes(-current.Minute);
current = current.AddHours(-current.Hour);
current = current.AddDays(7 - (int)current.DayOfWeek);
break;
case RollPoint.TopOfMonth:
current = current.AddMilliseconds(-current.Millisecond);
current = current.AddSeconds(-current.Second);
current = current.AddMinutes(-current.Minute);
current = current.AddHours(-current.Hour);
current = current.AddDays(1 - current.Day); /* first day of month is 1 not 0 */
current = current.AddMonths(1);
break;
}
return current;
}
#endregion
#region Private Instance Fields
/// <summary>
/// This object supplies the current date/time. Allows test code to plug in
/// a method to control this class when testing date/time based rolling.
/// </summary>
private IDateTime m_dateTime = null;
/// <summary>
/// The date pattern. By default, the pattern is set to <c>".yyyy-MM-dd"</c>
/// meaning daily rollover.
/// </summary>
private string m_datePattern = ".yyyy-MM-dd";
/// <summary>
/// The actual formatted filename that is currently being written to
/// or will be the file transferred to on roll over
/// (based on staticLogFileName).
/// </summary>
private string m_scheduledFilename = null;
/// <summary>
/// The timestamp when we shall next recompute the filename.
/// </summary>
private DateTime m_nextCheck = DateTime.MaxValue;
/// <summary>
/// Holds date of last roll over
/// </summary>
private DateTime m_now;
/// <summary>
/// The type of rolling done
/// </summary>
private RollPoint m_rollPoint;
/// <summary>
/// The default maximum file size is 10MB
/// </summary>
private long m_maxFileSize = 10*1024*1024;
/// <summary>
/// There is zero backup files by default
/// </summary>
private int m_maxSizeRollBackups = 0;
/// <summary>
/// How many sized based backups have been made so far
/// </summary>
private int m_curSizeRollBackups = 0;
/// <summary>
/// The rolling file count direction.
/// </summary>
private int m_countDirection = -1;
/// <summary>
/// The rolling mode used in this appender.
/// </summary>
private RollingMode m_rollingStyle = RollingMode.Composite;
/// <summary>
/// Cache flag set if we are rolling by date.
/// </summary>
private bool m_rollDate = true;
/// <summary>
/// Cache flag set if we are rolling by size.
/// </summary>
private bool m_rollSize = true;
/// <summary>
/// Value indicating whether to always log to the same file.
/// </summary>
private bool m_staticLogFileName = true;
/// <summary>
/// FileName provided in configuration. Used for rolling properly
/// </summary>
private string m_baseFileName;
#endregion Private Instance Fields
#region Static Members
/// <summary>
/// The 1st of January 1970 in UTC
/// </summary>
private static readonly DateTime s_date1970 = new DateTime(1970, 1, 1);
#endregion
#region DateTime
/// <summary>
/// This interface is used to supply Date/Time information to the <see cref="RollingFileAppender"/>.
/// </summary>
/// <remarks>
/// This interface is used to supply Date/Time information to the <see cref="RollingFileAppender"/>.
/// Used primarily to allow test classes to plug themselves in so they can
/// supply test date/times.
/// </remarks>
public interface IDateTime
{
/// <summary>
/// Gets the <i>current</i> time.
/// </summary>
/// <value>The <i>current</i> time.</value>
/// <remarks>
/// <para>
/// Gets the <i>current</i> time.
/// </para>
/// </remarks>
DateTime Now { get; }
}
/// <summary>
/// Default implementation of <see cref="IDateTime"/> that returns the current time.
/// </summary>
private class DefaultDateTime : IDateTime
{
/// <summary>
/// Gets the <b>current</b> time.
/// </summary>
/// <value>The <b>current</b> time.</value>
/// <remarks>
/// <para>
/// Gets the <b>current</b> time.
/// </para>
/// </remarks>
public DateTime Now
{
get { return DateTime.Now; }
}
}
#endregion DateTime
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -