Photo by pxhere.com

Monitoring your Xamarin application using NLog

NLog is one of the best tools to monitor your application with local files. Discover how!

Posted by Damien Aicheh on June 06, 2019 · 8 mins

In my previous tutorial I explained why monitoring your application is critical, let’s see an example with NLog.

Let’s start using NLog and create a log service that can be reused across your applications.

Quick setup

First of all, in your platform project, you need to install NLog.Config package. If it’s not automatically done, add a NLog.config file as EmbeddedResource in your application.

Configure NLog.config

This config file will be used to specify:

  • Mobile’s disk location
  • Your logs format
  • If you want your logs to be printed in the console and / or in a file

Because each platform has a different OS, the paths to save the logs files are not the same.

Here is the implementation of NLog.config for your Xamarin.Android project:

<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://www.nlog-project.org/schemas/NLog.xsd NLog.xsd"
      autoReload="true"
      throwExceptions="false"
      internalLogFile="c:\temp\nlog-internal.log">

  <targets>
    <target xsi:type="File" name="f" fileName="${specialfolder:folder=MyDocuments}/logs/${shortdate}.log" layout="${longdate} ${uppercase:${level}} ${message}" />
    <target xsi:type="Console" name="console" layout="${longdate} ${uppercase:${level}} ${message}" />
  </targets>

  <rules>
    <logger name="*" minlevel="Debug" writeTo="f" />
    <logger name="*" minlevel="Debug" writeTo="console" />
  </rules>
</nlog>

And now the implementation for the Xamarin.iOS project:

<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://www.nlog-project.org/schemas/NLog.xsd NLog.xsd"
      autoReload="true"
      throwExceptions="false">

  <targets>
    <target xsi:type="File" name="f" fileName="${specialfolder:folder=MyDocuments}/../Library/logs/${shortdate}.log" layout="${longdate} ${uppercase:${level}} ${message}" />
    <target xsi:type="Console" name="console" layout="${longdate} ${uppercase:${level}} ${message}" />
  </targets>

  <rules>
    <logger name="*" minlevel="Debug" writeTo="f" />
    <logger name="*" minlevel="Debug" writeTo="console" />
  </rules>
</nlog>

Load the config file

Each platform has a different location to the NLog.config so we need to include the file inside the assembly for each project platform.

For Xamarin.Android, add a new method named Bootstraping to your MainActivity.cs and call it inside the OnCreate. Same process for Xamarin.iOS, add the new method called Bootstraping in the AppDelegate.cs inside FinishedLaunching method.

private void Bootstraping()
{
    var assembly = this.GetType().Assembly;
    var assemblyName = assembly.GetName().Name;
}

Now that we have the assembly path, we can create a new class called LogService in our shared code (.Net Standard project for example). We need to add the NLog package to the project package to create a Logger. The LogService initialize our logger and includes all the methods to log any data.

Here is the initialize method:

private Logger logger;

public void Initialize(Assembly assembly, string assemblyName)
{
    var location = $"{assemblyName}.NLog.config";
    var stream = assembly.GetManifestResourceStream(location);
    LogManager.Configuration = new XmlLoggingConfiguration(XmlReader.Create(stream), null);
    this.logger = LogManager.GetCurrentClassLogger();
}

Implement a reusable Log service

The LogService

This section presents the implementation for the LogService :

public class LogService : ILogService
{
    private Logger logger;

    public void Initialize(Assembly assembly, string assemblyName)
    {
        var location = $"{assemblyName}.NLog.config";
        var stream = assembly.GetManifestResourceStream(location);
        LogManager.Configuration = new XmlLoggingConfiguration(XmlReader.Create(stream), null);
        this.logger = LogManager.GetCurrentClassLogger();
    }

    public void LogDebug(string message)
    {
        this.logger.Info(message);
    }

    public void LogError(string message)
    {
        this.logger.Error(message);
    }

    public void LogFatal(string message)
    {
        this.logger.Fatal(message);
    }

    public void LogInfo(string message)
    {
        this.logger.Info(message);
    }

    public void LogWarning(string message)
    {
        this.logger.Warn(message);
    }
}

I called the basic methods of the logger object just to show you a simple but useful example. Feel free to adapt it according to your need. I recommend to create the associated interface to use dependency injection. The definition of an interface makes it easier to replace NLog by another tool if required, you will just required to modify the implementation of LogService.

Start the logger

Go back to your Bootstraping method in each platform and start the LogService:

new LogService().Initialize(assembly, assemblyName);

Where can I see my logs files?

You will probably want to see if everythings is setup correctly and check what the logger is writing in the file. Call this line in your shared code to get the path of the application data:

 System.Diagnostics.Debug.WriteLine($"App folder path :{Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)}");

For your iOS Simulator, open a terminal and navigate to the app folder path, the log files will be inside Library/logs like we configured in NLog.config.

In Android it’s a bit different, with your emulator opened, go to your terminal and find your device using:

adb devices

Copy the id of the emulator in the list and open the following shell:

adb -s EMULATOR_ID_TO_REPLACE shell

Then navigate to the application folder, the logs files will be inside the /logs/ folder like we specified in the NLog.config file.

Implement a method in your application that sends logs by email for an easier access.

Final touch

I created a complete and simple example of this code using dependency injection with MvvmLightLibs to show you how it can be used in a project and how easy to reuse it in your project and improve your application.

You will find full source code in this Github repository.

Happy coding!

You liked this tutorial? Leave a star in the associated Github repository!

Do not hesitate to follow me on to not miss my next tutorial!