Search code examples
c#log4netlog4net-appender

log4net using both BufferedAppender and RollingFileAppender


I have a problem similar to several other already discussed here and also on log4net manual, but I need a bit more complex behaviour.

I would like to log Info, Warn, as well as Error events. I also want to "dump" latest 50 events (Debug, Info and Warn) when I get an error I would like to write both this logs to the same logfile file.

I know something "similar" is possible with BufferedAppender, but I tried and I only got the dump when there is an error, so I loose all the Info and Warn events if I do not get any error (If I lower the threshold of BufferedAppender I get all the logs every event).

I think I need to create a ForwardingAppender and a BufferedAppender that both forward to the same RollingFileAppender, but I do not know how to correctly do it.

Is it possible with versione 1.2.10 for Fx 2.0 ? I need this for customer request...

Moreover, can you please write the solution both in XML .config file and also in C# programmatically configuration? Thanks


Solution

  • After 2 days of trying I finally found the solution.

    (I configure it programmatically, if you need the xml configuration I'm sorry you have to figure it out)

        log4net.Appender.ForwardingAppender direct; // Global variable to enable threshold change
    
        public Form1()
        {
            InitializeComponent();
    
            // configuring Log4net
            log4net.Appender.RollingFileAppender roller = new log4net.Appender.RollingFileAppender();
            roller.AppendToFile = true;
            roller.File = "TestLog.log";
            roller.MaxSizeRollBackups = 10;
            roller.DatePattern = "yyyyMMdd";
            roller.Layout = new log4net.Layout.PatternLayout("%date  %-5level  - %message%newline%exception");
            roller.RollingStyle = log4net.Appender.RollingFileAppender.RollingMode.Date;
            roller.StaticLogFileName = true;
            roller.ActivateOptions();
            //log4net.Config.BasicConfigurator.Configure(roller); Do not activate logger, otherwise you will have all events twice
    
            direct = new log4net.Appender.ForwardingAppender();
            direct.Name = "direct";
            direct.Threshold = log4net.Core.Level.Warn;
            direct.AddAppender(roller);
            direct.ActivateOptions();
            log4net.Config.BasicConfigurator.Configure(direct);
    
            log4net.Appender.BufferingForwardingAppender buffer = new log4net.Appender.BufferingForwardingAppender();
            buffer.Name = "Buffer";
            buffer.BufferSize = 50;
            buffer.Lossy = true;
            buffer.Evaluator = new log4net.Core.LevelEvaluator(log4net.Core.Level.Error);
            buffer.AddAppender(roller);
            buffer.ActivateOptions();
            log4net.Config.BasicConfigurator.Configure(buffer);
        }
    
        private void numericUpDown1_ValueChanged(object sender, EventArgs e)
        {
            if (numericUpDown1.Value == 0)
                direct.Threshold = log4net.Core.Level.Debug;
            if (numericUpDown1.Value == 1)
                direct.Threshold = log4net.Core.Level.Info;
            if (numericUpDown1.Value == 2)
                direct.Threshold = log4net.Core.Level.Warn;
            if (numericUpDown1.Value == 3)
                direct.Threshold = log4net.Core.Level.Error;
        }
    

    If you have a cleaner way to do it, please let me know.

    Also I was not able to log in different layouts nor to add "**** Dump start ****" and "**** Dump end ****" at the beginning and ending of the dump done by BufferingForwardingAppender.

    Let me know if you know how to do it.