Search code examples
c#logginguwplog4netlog4net-configuration

How to configure logging via log4net in an UWP App


I have an UWP app that uses some of my libraries. Such libraries use log4net for logging purpose, and are shared across a number of projects, not only UWP.

I'd like to configure log4net via the usual confi section in the XML config file, but I cannot find a way to do this in an UWP project, since there isn't an app.config file.

Where should I put the following section?

<log4net>
    <appender name="Console" type="log4net.Appender.ConsoleAppender">
        <layout type="log4net.Layout.PatternLayout">
            <conversionPattern value="%date - %message%newline" />
        </layout>
    </appender>

    <appender name="RollingFile" type="log4net.Appender.RollingFileAppender">
        <file value="log\mylog.log" />
        <appendToFile value="true" />
        <maximumFileSize value="2000KB" />
        <maxSizeRollBackups value="20" />

        <layout type="log4net.Layout.PatternLayout">
            <conversionPattern value="%date - %message%newline" />
        </layout>
    </appender>

    <root>
        <level value="INFO" />
        <appender-ref ref="Console" />
        <appender-ref ref="RollingFile" />
    </root>
</log4net>

Thank you!


Solution

  • To complete pfx answer, if you are using netStandard, you will have to use Configure overloads with an additional parameter log4net.Repository.ILoggerRepository.

    I haven't been able to use the ConsoleAppender and switch to the DebugAppender.

    You cannot use relative path in UWP with RollingFileAppender since log4net will not have permission to create file in the install location of your application. I think it could work with a full path but I have seen some permissions issues (you should activate debug mode of log4net for this).

    Finally, I also made a Custom Appender which writes file in the Local Storage of your application. Here is the code which should be enhanced for production use.

    namespace AppWithLog4net
    {
        public class LocalStorageFileAppender : log4net.Appender.TextWriterAppender
        {
    
            private Stream m_stream;
    
            public LocalStorageFileAppender() : base() {  }
    
            protected override void PrepareWriter()
            {
                IAsyncOperation<Windows.Storage.StorageFile> task = Windows.Storage.ApplicationData.Current.LocalCacheFolder.CreateFileAsync("localStorage.log", 
                                                                                Windows.Storage.CreationCollisionOption.GenerateUniqueName);
                Windows.Storage.StorageFile file = task.GetAwaiter().GetResult();
                m_stream = file.OpenStreamForWriteAsync().Result;
    
                QuietWriter = new log4net.Util.QuietTextWriter(new StreamWriter(m_stream, Encoding.UTF8), ErrorHandler);
                WriteHeader();
            }
    
            protected override void Reset()
            {
                m_stream.Dispose();
                m_stream = null;
                base.Reset();
            }
        }
    }
    

    With the following config file:

    <log4net debug="true">
      <appender name="Console" type="log4net.Appender.DebugAppender">
        <layout type="log4net.Layout.PatternLayout">
          <conversionPattern value="%date - %message%newline" />
        </layout>
      </appender>
    
      <appender name="LocalStorageFile" type="AppWithLog4net.LocalStorageFileAppender, AppWithLog4net">
        <layout type="log4net.Layout.PatternLayout">
          <conversionPattern value="%date - %message%newline" />
        </layout>
      </appender>
    
      <root>
        <level value="INFO" />
        <appender-ref ref="Console" />
        <appender-ref ref="LocalStorageFile" />
      </root>
    </log4net>