Friday, June 29, 2012

Logging using Log4Net in WPF

log4net is best logging framework available for .Net.

Let's start with step by step, how to log error in your application.

Step 1:first download latest log4net dll.

click Log4Net dll to download and add reference in your project.

Step 2: Create log4net.config application configuration file for configuration settings.

FileName : log4net.config

there are many ways to create log file and message/error format.

I have created 2 formats, one for create log file within folder, one for create log file directly within Debug folder.

Format 1 : Create folder named Log and create log file dynamically date wise and save in Debug folder.

<log4net debug="true">
    <appender name="RollingLogFileAppender" 
                type="log4net.Appender.RollingFileAppender">
      <file value="Logs\log" />
      <staticLogFileName value="false"/>
      <appendToFile value="true" />
      <rollingStyle value="Date" />
      <datePattern value=" yyyy-MM-dd&quot;.xml&quot;"/>
      <layout type="log4net.Layout.PatternLayout">        
        <!--<param name="ConversionPattern" 
               value="%d [%t] %-5p %c %m%n" />-->
        <conversionPattern 
           value="%date [%thread] %-5level %logger ==> %message%newline"/>
      </layout>
    </appender>

    <root>
      <level value="INFO" />
      <appender-ref ref="RollingLogFileAppender" />
      <appender-ref ref="AdoNetAppender" />
    </root>
  </log4net>

Format 2 : Create log file named hirenlog.txt and save in Debug folder.

<log4net debug="true">
  <appender name="LogFileAppender" type="log4net.Appender.FileAppender">
    <param name="File" value="hirenlog.txt" />
    <param name="AppendToFile" value="true" />
    <layout type="log4net.Layout.PatternLayout">
      <param name="Header" value="[Header]\r\n" />
      <param name="Footer" value="[Footer]\r\n" />
      <param name="ConversionPattern" value="%d [%t] %-5p %c %m%n" />
    </layout>
  </appender>
  <root>
    <level value="INFO" />
    <appender-ref ref="LogFileAppender" />
  </root>
</log4net>
 
Step 3: Right click on log4net.config file and go to properties and set 
"Copy to Output Directory" property value to "Copy if newer" as highlighted in below image.


Step 4: Open AssemblyInfo.cs file from properties and add below line at end of file.

[assembly: log4net.Config.XmlConfigurator(ConfigFile = "log4net.config", Watch = true)]


Step 5 : Create Logger Class.

    public interface ILogger
    {
        void LogException(Exception exception);
        void LogError(string message);
        void LogWarningMessage(string message);
        void LogInfoMessage(string message);
    }
    public class Logger : ILogger
    {      
        private static ILog log = null; 
        static Logger()
        {
            //var log4NetConfigDirectory = 
            //AppDomain.CurrentDomain.RelativeSearchPath ?? AppDomain.CurrentDomain.BaseDirectory;
            //var log4NetConfigFilePath = Path.Combine(log4NetConfigDirectory, "log4net.config");
            //log4net.Config.XmlConfigurator.ConfigureAndWatch(new FileInfo(log4NetConfigFilePath));
            log = LogManager.GetLogger(typeof(Logger));
            log4net.GlobalContext.Properties["host"] = Environment.MachineName;
        }
        public Logger(Type logClass)
        {
            log = LogManager.GetLogger(logClass);
        }

        #region ILogger Members
        public void LogException(Exception exception)
        {
            if (log.IsErrorEnabled)
                log.Error(string.Format(CultureInfo.InvariantCulture, "{0}", exception.Message), exception);
        }
        public void LogError(string message)
        {
            if (log.IsErrorEnabled)
                log.Error(string.Format(CultureInfo.InvariantCulture, "{0}", message));
        }
        public void LogWarningMessage(string message)
        {
            if (log.IsWarnEnabled)
                log.Warn(string.Format(CultureInfo.InvariantCulture, "{0}", message));
        }
        public void LogInfoMessage(string message)
        {
            if (log.IsInfoEnabled)
                log.Info(string.Format(CultureInfo.InvariantCulture, "{0}", message));
        }
        #endregion
    }

Above class configures log4net using xml file (log4net.config) and creates instance of ILog, now you will use this class for logging errors from ViewModels.

Step 6 : In you ViewModel Initialize ILogger class and logs errors.

  internal class MainWindowViewModel
  {
     ILogger logger = new Logger(typeof(MainWindowViewModel));
     public MainWindowViewModel()
     {
        logger.LogError("Error while downloading data"); 
     } 
  }

so, this is simple way to logs you error and exception details.

6 comments:

  1. Very helpful in getting this setup quickly in WPF. Thank you!

    ReplyDelete
  2. Sorry, but it is not working for me if I do not include configsection in app.config

    ReplyDelete
  3. This is not working for me, maybe some code missing in app.xaml.cs

    private static readonly ILog Log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

    protected override void OnStartup(StartupEventArgs e)
    {
    log4net.Config.XmlConfigurator.Configure();
    //Log.Info("Hello World");
    base.OnStartup(e);
    }

    after placing these two lines it worked for me I found them at https://gist.github.com/bobbychopra/2897163

    Thanks,
    Abdul Mateen.

    ReplyDelete
  4. Must uncomment the commented lines in the following...

    static Logger()
    {
    //var log4NetConfigDirectory =
    //AppDomain.CurrentDomain.RelativeSearchPath ?? AppDomain.CurrentDomain.BaseDirectory;
    //var log4NetConfigFilePath = Path.Combine(log4NetConfigDirectory, "log4net.config");
    //log4net.Config.XmlConfigurator.ConfigureAndWatch(new FileInfo(log4NetConfigFilePath));
    log = LogManager.GetLogger(typeof(Logger));
    log4net.GlobalContext.Properties["host"] = Environment.MachineName;
    }

    as...

    var log4NetConfigDirectory = AppDomain.CurrentDomain.RelativeSearchPath ?? AppDomain.CurrentDomain.BaseDirectory;
    var log4NetConfigFilePath = Path.Combine(log4NetConfigDirectory, "log4net.config");
    log4net.Config.XmlConfigurator.ConfigureAndWatch(new FileInfo(log4NetConfigFilePath));

    ReplyDelete