Hi All,

I'm interested in feedback about some (potential) enhancements to
log4net that would make it more robust in production ASP.NET
environments.  

I'm willing to write the code and test it, then submit back to this
public forum once things are debugged, but wanted to get feedback before
starting to see if this makes sense to pursue.

-Doug

Doug de la Torre
Lead Developer
UGS

Log4net enhancements:

1)  Allow log4net to format (like string.Format) in .Debug, .Info,
.Warn, etc.

        (Already submitted code to do this in a previous post...but
worth mentioning all the same)

        lets you use 

                log.Debug( "message with param {0} and param {1}",
param1, param2 );

        instead of 

                log.Debug( string.Format( "message with param {0} and
param {1}", param1, param2 ) );

2)  Allow log4net to impersonate a user via app-specific mechanism.

        Currently, log4net opens files as the user who logs a message.
This means on a site with
        lots of users, in order to ensure fail-safe logging, all users
must have full permissions
        to the folder where logging occurs.  This is problematic, since
customers are reluctant
        to open up folders will full access, and when they are willing,
it is still tough to keep
        permissions on the folder in-sync with all the site users.  If
even one user doesn't have
        full permissions, logging can fail (and stop thereafter) for all
users.

        Impact would be to the RollingFileAppender and the FileAppender
classes.

        How?  

        Introduce a FileFactory mechanism, and specify the type via the
XML config file.
        Most users would see no difference, but this would give us a
point of flexibility
        to control how file I/O is done.

        Default factory does what log4net currently does (all file I/O
done as current user)
        When there is no XML override, then it falls back to using the
current approach of file I/O, 
        using a 'default' factory (which would do raw file I/O).

        Our application could could override via config XML

                <log4net>
                        <fileFactory
type="Customer.Specified.MyFileFactory,mydll" />
                </log4net>

        Our application's file factory could implement IFileFactory

                public interface IFileFactory
                {
                        void CreateDirectory( string directoryToFile );

                        StreamWriter OpenFile( string fileName, bool
append, string encoding );

                        IFileInfo NewFileInfo( string fileName );
                }

        Then, when the IFileFactory methods are called, we could do
impersonation around the file
        I/O, allowing the logfile to be created using a single account.
By ensuring that one account
        has full permissions on the log folder, it is easier to ensure
logging will always succeed
        for all users.

        Note that the messages themselves would still be logged as the
windows identity of the user that 
        was running when the message was logged.  Only the file creation
(or deletion) would go through a 
        factory, allowing those operations to be done differently if
needed.
        
        Need to impersonate for the FileInfo.Delete, FileInfo.MoveTo
checks, as well as the OpenFile call,
        and FileInfo.Directory.GetFiles

        Since FileInfo is sealed, need to create wrapper interfaces for
common file actions:

                public interface IFileInfo
                {
                        bool Exists { get; }

                        long Length { get; }

                        string DirectoryName { get; }

                        IDirectoryInfo Directory { get; }

                        DateTime LastWriteTime { get; }

                        void Delete();

                        void MoveTo( string destinationFile );
                }

                public interface IDirectoryInfo
                {
                        bool Exists { get; }

                        IFileInfo[] GetFiles( string wildcardPattern );
                }

3)  Allow log4net to retry if a file I/O fails

        This partially addresses issues with multiple users when some
don't have permissions.
        By adding ability to try (if no logger is currently assigned),
it could stand back
        up if logging failed (for a user that doesn't have permissions),
allowing messages
        for a user that did to start logging again.

        Currently, if the user doesn't have permissions to open the
file, the appender
        shuts down and never logs a message after that.  I like to call
this a 'black hole',
        since it only takes one of the problems below to occur before
logging can stop forever 
        and never recover, thus making it unreliable in a production
environment.

        I've seen this happen for these conditions:

        1)  The log file is already open when log4net tries to open it
                - This happens more frequently with RollingFileAppender
since it does lots of open/closes
                
        2)  An app that uses impersionation (like an ASP.NET app with
Windows authentication)
            has users from different permission groups, and not all
users have permission to the
            folder where log files are recorded

        Impact would be in the FileAppender and RollingFileAppender
classes.

Reply via email to