- Xamarin
- NLog
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.
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.
This config file will be used to specify:
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>
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();
}
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
.
Go back to your Bootstraping
method in each platform and start the LogService
:
new LogService().Initialize(assembly, assemblyName);
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.
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!