How to configure log4net on Azure App Service

Although I fully recommend using Application Insights (see here) for monitoring your Azure features, I get asked sometimes how to configure log4net onto an Azure App Service.  So, this is how I did it.

  • Install the log4net.dll binary using NuGet
  • Configure the log4net name, type properties in the web.config
  • Configure the log4net properties
  • Modify the Global.asax Application_Start() method
  • Create an instance of the ILog interface
  • Create the directory on KUDU/SCM
  • Write the logs
  • Download and analyze

I updated a project I wrote about here to use the log4net capability.  I wanted to put it into my ASP.NET Core application, however it seems like it is not yet supported, at least while I was creating this one.  Therefore, integrated log4net into the Azure Apps Service that consumes the ASP.NET Core Web API instead of within the API itself.

Install the log4net.dll binary using NuGet

Install the log4Net (add the reference) by right-clicking on the project –> Manage NuGet packages.  Then search for and install the log4net binaries, as seen in Figure 1.

image

Figure 1, install log4net binaries for use with an Azure App Service

Configure the log4net name, type properties in the web.config

Add the <configSections> attribute to the web.config file between the already existing <configuration> attribute.

<configuration>
   <configSections>
     <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,Log4net"/>
   </configSections>
</configuration>

Configure the log4net properties

Add this configuration directly after the one added in the previous section

<log4net>
    <root>
      <level value="Debug"/>
      <appender-ref ref="LogFileAppender"/>
    </root>
    <appender name="LogFileAppender" type="log4net.Appender.RollingFileAppender">
      <param name="File" value="D:\Home\LogFiles\Log4Net\Log4Net.log"/>
      <param name="AppendToFile" value="true"/>
      <rollingStyle value="Size"/>
      <maxSizeRollBackups value="10"/>
      <maximumFileSize value="3MB"/>
      <staticLogFileName value="true"/>
      <layout type="log4net.Layout.PatternLayout">
        <param name="ConversionPattern" value="%date [%thread] %-5level %logger - %message%newline"/>
      </layout>
    </appender>
    <logger name="SleepyCore">
      <level value="INFO"/>
    </logger>
  </log4net>

A few of the configurations I would like to call out are:

  • “File” with a value of “D:\Home\LogFiles\Log4Net\Log4Net.log” – have a look at my other post here where I discuss the file structure of an Azure App Service.  Note that although you can read from and write to the D:\local directory (using FileZilla, for example), it does not mean your application can.  But your application can write to the D:\home\LogFiles\*.
  • “maximumFileSize” – it is always a good idea to set this so you do not run out of drive space, plus, if/when the file gets very large it can cause performance issues
  • “logger name=’SleepyCore’” – this needs to match the parameter I pass to the GetLogger() method later in the “Create an instance of the ILog interface” section
  • “level value=’INFO’” – will inform the logger that I want calls to log.Info() to be written to the log, see section “Write the logs”.  If the value was set to Debug or Error, then the Info calls would not be logged.

Modify the Global.asax Application_Start() method

Add the instantiation of the log4net features to the Global.asax file.  This is kind of ‘old school’ but it does work.  Also, consider adding some code in the Application_Error() method as well to log any application error.

<%@ Import Namespace="log4net" %>
<%@ Import Namespace="System.IO" %>

<script runat="server">
  void Application_Start(object sender, EventArgs e)
  {
    log4net.Config.XmlConfigurator.Configure(new FileInfo(Server.MapPath("~/Web.config")));
  }

void Application_Error(object sender, EventArgs e)
  {
   ILog log = LogManager.GetLogger("SleepyCore");
   Exception ex = Server.GetLastError();
   log.Debug("++++++++++++++++++++++++++++");
   log.Error("Exception - \n" + ex);
   log.Debug("++++++++++++++++++++++++++++");
  }

Create an instance of the ILog interface

In the Default.aspx.cs file I added the following.

using log4net;


public partial class _Default : System.Web.UI.Page
{
  private static readonly ILog log = LogManager.GetLogger("SleepyCore");
  ...
}

Create the directory on KUDU/SCM

I wrote an article here about accessing KUDU/SCM.  Once you login, click on the the Debug console –> CMD and navigate to the D:\Home\LogFiles directory and then create a folder named Log4Net, Figure 2, or one that matches the ‘File’ value you set in the “Configure the log4net properties” earlier.  This is the place where the log file will be written to.

image

Figure 2, create Log4Net directory on KUDU/SCM azure app service

Write the logs

In my consumer code, I added code within the Page_Load() method, similar to the following.

protected void Page_Load(object sender, EventArgs e)
{
  try
  {
   log.Info("Begin - Page_Load() at " + DateTime.Now.ToString("hh.mm.ss.ffffff"));
   log.Info("------------------------------------------------------------------");
   ......
   log.Info("Begin - request.GetResponse() at " + DateTime.Now.ToString("hh.mm.ss.ffffff"));
   System.Net.WebResponse response = request.GetResponse();
   log.Info("End - request.GetResponse() at " + DateTime.Now.ToString("hh.mm.ss.ffffff"));
   .....
   log.Info("------------------------------------------------------------------");
   log.Info("End - Page_Load() at " + DateTime.Now.ToString("hh.mm.ss.ffffff"));
  }
  catch (Exception ex)
  {
   labelAPI.Text = ex.Message;
   log.Debug("++++++++++++++++++++++++++++");
   log.Error("Exception - \n" + ex);
   log.Debug("++++++++++++++++++++++++++++");
  }
}

Simply paste the code around any method you would like to track for time.  If your methods contain parameters, you can also dump out the values of them with each method call.

Notice that I use the log.Info(), log.Debug() and log.Error().  In order for the log.Info() method to trigger I must set the logger value to INFO, see section “Configure the log4net properties”.  If this value is set to Debug or Error, then the calls to the log.Info() method will not fire and will not be written to the log.

Once the code is deployed and the Page_Load() method is called, a log is written in the defined format and in the defined location, see Figure 3.

image

Figure 3, log Log4Net for an azure app service

Download and analyze

You can download the logs using FileZilla or any FTP tool, or you can download them from KUDU/SCM by clicking the download button also shown in Figure 3.

I looked for some tools to analyze these logs, but as they are uniquely configurable, I was unable to find a tool which could manage them, honestly did not spend a lot of time looking, as there are so many better ways to get insights into the operations of your application.