views:

598

answers:

3

I am going to write out a separate log for each time I do a certain process in my WCF service. I have a standard log for the entire application already using log4net. Should I just add an appender and filter for the particular process, then remove it? This process deals with processing a file that was uploaded. Any other ideas???

A: 

I'ved do something similiar before, we used code something like this:

Ollie

 class Program
{
    static void Main(string[] args)
    {
        log4net.Config.BasicConfigurator.Configure();

        var file = Path.Combine(Directory.GetCurrentDirectory(), Guid.NewGuid() + ".log");
        var log = InitialiseLogToFile(file);
        log.Info("Made it here!");
        log.Error("Made it here!");

        var file2 = Path.Combine(Directory.GetCurrentDirectory(), Guid.NewGuid() + ".log");
        var log2 = InitialiseLogToFile(file2);
        log2.Info("Made it here!");
        log2.Error("Made it here!");
    }

    public static ILog InitialiseLogToFile(string file)
    {
        LogManager.ResetConfiguration();
        var hierarchy = (Hierarchy)LogManager.GetLoggerRepository();

        var patternLayout = new PatternLayout();
        patternLayout.ConversionPattern = "%d [%t] %-5p %c [%x] - %m%n";
        patternLayout.ActivateOptions();

        var appender = new FileAppender {File = file, AppendToFile = true, Layout = patternLayout};
        appender.ActivateOptions();

        var logger = (Logger)hierarchy.GetLogger(file);
        logger.AddAppender(appender);
        hierarchy.Configured = true;

        return LogManager.GetLogger(file);
    }
}
AWC
The problem I have, which was probably not clear from my question. I am running a file after an upload, and I want a log file for each processing of a file. If add an appender and dont use a filter I will get all log messages added to that file as well instead of ONLY the messages for processing the one file.
CSharpAtl
that's why we called 'ResetConfiguration'...
AWC
But that means now I only have 1 appender and if there are other things in the app that need to be logged, they are going to get logged to the new file...I ONLY want logging from this process to go in the new file and all other logging in the regular log file.
CSharpAtl
A: 

Okay how about the you create a custom implementation of the ILog interface that also implements IDisposable - you add the appender when it's created and remove it when it's disposed...

eg.

class Program
{
    static void Main(string[] args)
    {
        log4net.Config.BasicConfigurator.Configure();

        var file = Path.Combine(Directory.GetCurrentDirectory(), Guid.NewGuid() + ".log");
        using (var log = new CustomFileLogger(file))
        {
            // Process file...
            log.Info("file: Made it here!");
            log.Error("file: Made it here!");
        }

        var file2 = Path.Combine(Directory.GetCurrentDirectory(), Guid.NewGuid() + ".log");
        using (var log = new CustomFileLogger(file2))
        {
            // Process file...
            log.Info("file2: Made it here!");
            log.Error("file2: Made it here!");
        }
    }
}

public sealed class CustomFileLogger : ILog, IDisposable
{
    private ILog _log;
    private FileAppender _appender;
    private string _file;

    public CustomFileLogger(string file)
    {
        _file = file;

        var hierarchy = (Hierarchy)LogManager.GetRepository();
        hierarchy.Configured = false;

        var patternLayout = new PatternLayout();
        patternLayout.ConversionPattern = "%d [%t] %-5p %c [%x] - %m%n";
        patternLayout.ActivateOptions();

        var appender = new FileAppender { File = file, AppendToFile = true, Layout = patternLayout };
        appender.ActivateOptions();

        var logger = (Logger)hierarchy.GetLogger(file);
        logger.AddAppender(appender);

        hierarchy.Configured = true;
        _log = LogManager.GetLogger(file);
    }

    public ILogger Logger
    {
        get { return _log.Logger; }
    }

    public void Dispose()
    {
        var hierarchy = (Hierarchy)LogManager.GetRepository();
        hierarchy.Configured = false;

        var logger = (Logger)hierarchy.GetLogger(_file);
        logger.RemoveAppender(_appender);

        hierarchy.Configured = false;


        _appender = null;
        _log = null;
        _file = null;
    }

    public void Debug(object message)
    {
        _log.Debug(message);
    }

    public void Debug(object message, Exception exception)
    {
        _log.Debug(message, exception);
    }

    public void DebugFormat(string format, params object[] args)
    {
        _log.DebugFormat(format, args);
    }

    public void DebugFormat(string format, object arg0)
    {
        _log.DebugFormat(format, arg0);
    }

    public void DebugFormat(string format, object arg0, object arg1)
    {
        _log.DebugFormat(format, arg0, arg1);
    }

    public void DebugFormat(string format, object arg0, object arg1, object arg2)
    {
        _log.DebugFormat(format, arg0, arg1, arg2);
    }

    public void DebugFormat(IFormatProvider provider, string format, params object[] args)
    {
        _log.DebugFormat(provider, format, args);
    }

    public void Info(object message)
    {
        _log.Info(message);
    }

    public void Info(object message, Exception exception)
    {
        _log.Info(message, exception);
    }

    public void InfoFormat(string format, params object[] args)
    {
        _log.InfoFormat(format, args);
    }

    public void InfoFormat(string format, object arg0)
    {
        _log.InfoFormat(format, arg0);
    }

    public void InfoFormat(string format, object arg0, object arg1)
    {
        _log.InfoFormat(format, arg0, arg1);
    }

    public void InfoFormat(string format, object arg0, object arg1, object arg2)
    {
        _log.InfoFormat(format, arg0, arg1, arg2);
    }

    public void InfoFormat(IFormatProvider provider, string format, params object[] args)
    {
        _log.InfoFormat(provider, format, args);
    }

    public void Warn(object message)
    {
        _log.Warn(message);
    }

    public void Warn(object message, Exception exception)
    {
        _log.Warn(message, exception);
    }

    public void WarnFormat(string format, params object[] args)
    {
        _log.WarnFormat(format, args);
    }

    public void WarnFormat(string format, object arg0)
    {
        _log.WarnFormat(format, arg0);
    }

    public void WarnFormat(string format, object arg0, object arg1)
    {
        _log.WarnFormat(format, arg0, arg1);
    }

    public void WarnFormat(string format, object arg0, object arg1, object arg2)
    {
        _log.WarnFormat(format, arg0, arg1, arg2);
    }

    public void WarnFormat(IFormatProvider provider, string format, params object[] args)
    {
        _log.WarnFormat(provider, format, args);
    }

    public void Error(object message)
    {
        _log.Error(message);
    }

    public void Error(object message, Exception exception)
    {
        _log.Error(message, exception);
    }

    public void ErrorFormat(string format, params object[] args)
    {
        _log.ErrorFormat(format, args);
    }

    public void ErrorFormat(string format, object arg0)
    {
        _log.ErrorFormat(format, arg0);
    }

    public void ErrorFormat(string format, object arg0, object arg1)
    {
        _log.ErrorFormat(format, arg0, arg1);
    }

    public void ErrorFormat(string format, object arg0, object arg1, object arg2)
    {
        _log.ErrorFormat(format, arg0, arg1, arg2);
    }

    public void ErrorFormat(IFormatProvider provider, string format, params object[] args)
    {
        _log.ErrorFormat(provider, format, args);
    }

    public void Fatal(object message)
    {
        _log.Fatal(message);
    }

    public void Fatal(object message, Exception exception)
    {
        _log.Fatal(message, exception);
    }

    public void FatalFormat(string format, params object[] args)
    {
        _log.FatalFormat(format, args);
    }

    public void FatalFormat(string format, object arg0)
    {
        _log.FatalFormat(format, arg0);
    }

    public void FatalFormat(string format, object arg0, object arg1)
    {
        _log.FatalFormat(format, arg0, arg1);
    }

    public void FatalFormat(string format, object arg0, object arg1, object arg2)
    {
        _log.FatalFormat(format, arg0, arg1, arg2);
    }

    public void FatalFormat(IFormatProvider provider, string format, params object[] args)
    {
        _log.FatalFormat(provider, format, args);
    }

    public bool IsDebugEnabled
    {
        get { return _log.IsDebugEnabled; }
    }

    public bool IsInfoEnabled
    {
        get { return _log.IsInfoEnabled; }
    }

    public bool IsWarnEnabled
    {
        get { return _log.IsWarnEnabled; }
    }

    public bool IsErrorEnabled
    {
        get { return _log.IsErrorEnabled; }
    }

    public bool IsFatalEnabled
    {
        get { return _log.IsFatalEnabled; }
    }
}
AWC
+1  A: 

You can do this quite easily, but it means tying yourself to a specific implementation rather than the interfaces. For example:

log4net.ILog log = log4net.LogManager.GetLogger(loggerName);
log4net.Repository.Hierarchy.Logger logImpl = log.Logger as log4net.Repository.Hierarchy.Logger;
if (logImpl != null)
    logImpl.AddAppender(uploadLogAppender);
else {
    // unexpected logger type - handle this case somehow
}
ProcessUpload(); // does logging
if (logImpl != null)
    logImpl.RemoveAppender(uploadLogAppender);

As the appender is present only while ProcessUpload runs, this should give you the effect you need. uploadLogAppender is just a FileAppender instance with a filename determined by you, say on a per-upload basis.

Vinay Sajip