How to disable creation of empty log file on app start?

The problem with that approach is that then if the file exists but is read-only, or is in a directory which doesn't exist etc, you won't find out until another error is already causing problems. You really want to be confident that logging is working before the rest of the app starts.

There may be a way of doing this anyway, but if not I suspect that this is the reason.


I know this is an old question but I think this can be useful for someone else.

We came across a similar situation where it was required that the application shouldn't leave an empty log file if no errors occurred.

We solved it by creating the following custom LockingModel class:

public class MinimalLockDeleteEmpty : FileAppender.MinimalLock
{
    public override void ReleaseLock()
    {
        base.ReleaseLock();

        var logFile = new FileInfo(CurrentAppender.File);
        if (logFile.Exists && logFile.Length <= 0)
        {
            logFile.Delete();
        }
    }
}

It is derived from the FileAppender.MinimalLock class that will release the lock on the log file after writing each log message.

We added extra functionality that will delete the log file if it is still empty after the lock is released. It prevents the application from leaving empty error log files if the applications runs and exits without any errors.

Pros

  • It will still create an empty log file during the configuration phase of Log4Net, ensuring that logging is working before the rest of the app starts. However, the log file is deleted immediately.
  • It doesn't require you to turn off logging in your config file by setting threshold value to "OFF" and than, later on, turn on logging programmatically before writing your first log event.

Cons

  • This is most likely a slow method of managing your log files because the ReleaseLock method, and the check on the file length, will be called after every log event that is written to the log file. Only use it when you expect to have very few errors and it is a business requirement that the log file shouldn't exist when there are no errors.
  • The log files are created and deleted when empty. This might be a problem if you have other tools monitoring the log directory for file system changes. However, this was not a problem in our situation.

I actually found a way to do this in this thread:

http://www.l4ndash.com/Log4NetMailArchive/tabid/70/forumid/1/postid/18271/view/topic/Default.aspx

I've tested the first method and it works. Just in case that link is not longer good I'll reproduce the code here. Basically the author states that there are two ways of doing this.

First way:

Create a new locking model that only acquires a lock (and creates the file) if the appropriate threshold for that logger works.

public class MyLock : log4net.Appender.FileAppender.MinimalLock
{
      public override Stream AcquireLock()
      {
            if (CurrentAppender.Threshold == log4net.Core.Level.Off)
                  return null;

            return base.AcquireLock();
      }
}

Now in the config file, set the threshold to start out as:

<threshold value="OFF" />

and make sure you set this new LockingModel as you model:

<lockingModel type="Namespace.MyLock" />

I'm using this with a rolling file appender.

The second method is listed at the link. I haven't tried this technique but it seems to be technically sound.


The following worked for me.The first call to OpenFile() occurs when the logger is configured. Subsequent calls are when actual log message is generated.

class CustomFileAppender : RollingFileAppender
{
    private bool isFirstTime = true;
    protected override void OpenFile(string fileName, bool append)
    {
        if (isFirstTime)
        {
            isFirstTime = false;
            return;
        }

        base.OpenFile(fileName, append);
    }
}

And in the config file, change the appender

<log4net>
<appender name="RollingFile" type="<your namespace>.CustomFileAppender">
...
</log4net>

The sequence from log4Net source is as below:


  • The first call to OpenFile() is because of ActivateOptions() called from FileAppender's constructor.
  • When log message is generated, AppenderSkeleton's DoAppend() calls PreAppendCheck()
  • PreAppendCheck() is overridden in TextWriterAppender, the base of FileAppender.
  • The overridden PreAppendCheck() calls virtual PrepareWriter if the file is not yet open.
  • PrepareWriter() of FileAppender calls SafeOpenFile() which inturn calls OpenFile()