1
votes

Rather than roll a log after a date/time or specified maximum size, I want to be able to call a method like "ResetLog" that copies my "log.txt" to "log.txt.1" and then clears log.txt.

I've tried to implement that by doing something like this with a FileAppender, rather than a RollingFileAppender:

var appenders = log4net.LogManager.GetRepository().GetAppenders();
foreach (var appender in appenders) {
    var fa = appender as log4net.Appender.FileAppender;
    if (fa != null) {
        string logfile = fa.File;
        fa.Close();
        string new_file_path = CreateNextLogFile(logfile);
        fa.File = new_file_path;
        fa.ActivateOptions();
    }
}            

The file is closed and CreateNextLogFile() renames it. I then create a new log file and set the FileAppender to use it. However, I thought that ActivateOptions would go ahead and reconfigure the FileAppender with the desired settings. I've looked over the log4net documentation and don't see any other public methods that allow me to reopen the FileAppender after closing it. Can anyone recommend a way to implement the rollover? It would be nice if the RollingFileAppender had something like this, but I didn't see anything useful it its documentation, either.

1

1 Answers

4
votes

If we look at the RollingFileAppender we can see that the mechanism for rolling over consists of closing the file, renaming existing files (optional) and opening it again:

// log4net.Appender.RollingFileAppender
protected void RollOverSize()
{
    base.CloseFile();
    // debug info removed
    this.RollOverRenameFiles(this.File);
    if (!this.m_staticLogFileName && this.m_countDirection >= 0)
    {
        this.m_curSizeRollBackups++;
    }
    this.SafeOpenFile(this.m_baseFileName, false);
}

Unfortunately the CloseFile/SafeOpenFile methods are protected which means you cannot access it from the outside (not easily). So your best bet would be to write an appender inheriting from RollingFileAppender, and to override the virtual AdjustFileBeforeAppend which is called before any logging event is added to the appender.

There you can decide what are the conditions of the roll if any must occur. An idea would be to create a static event that your custom rolling appender suscribes to: when the event is triggered the appender makes a note of it (rollBeforeNextAppend = true;). As soon as you try and log next entry the appender will roll.

public class CustomRollingAppender: RollingFileAppender
{
    public CustomRollingAppender()
    {
        MyStaticCommandCenter.RollEvent += Roll;
    }

    public void Roll()
    {
        rollBeforeNextAppend = true;
    }

    public bool rollBeforeNextAppend {get; set;}
    public override void AdjustFileBeforeAppend()
    {
        if (rollBeforeNextAppend) {
            CloseFile();
            RollOverRenameFiles(File);
            SafeOpenFile(Filename, false);
            rollBeforeNextAppend = false;
        }
    }
}