Introduction
Here I am going to demonstrate server side logging mechanism for Silverlight applications using NLog 2.0. Using this you can have centralized place for all logs it can be log files, database, ftp etc.
Why to use NLog
There are two popular logging platforms are there NLog and Log4Net. NLog 2.0 release is focused on adding support for new platforms (Silverlight, .NET Framework 4, Windows Phone 7.x), improving logging architecture and manageability and addressing most frequently reported user issues. It fully supports async-only operations. So for Silverlight, NLog is the best choice.
We can think two options for permanent logging one Client side or Server side. Client side logging hampers performance and does not allow you to see logs at centralize place. Now question comes how server side logging can be achieved by using NLog in an efficient way.
Background
To implement this application, I am going to use the following technologies:
- Silverlight5 for the client tier
- WCF services -HTTP Binding (Optional for database interaction if want to use)
- WCF RIA Service V1.0 SP2
- NLog 2.0(Can be installed from http://nlog.codeplex.com/ )
Silverlight Business Application
Create new Silverlight business application. Name it to ‘BusinessAppMVVM’.
Web Project
I am going to add NLog.Config file to Web project.
Copy/paste following code to NLog.Config. I am not going in deep of different sections of config. Detail can be found in NLog documentation.
="1.0" ="utf-8"
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
-->
-->
<targets>
-->
<target name="file" xsi:type="AsyncWrapper" queueLimit="5000" overflowAction="Discard">
<target xsi:type="File" fileName="${basedir}/logs/${level}.txt"
layout="${longdate} ${logger} ${message}"
archiveFileName="${basedir}/logs/archives/${level}.{#####}.txt"
archiveAboveSize="10240"
archiveNumbering="Sequence"
concurrentWrites="true"
keepFileOpen="false"
encoding="iso-8859-2"/>
</target>
</targets>
<rules>
<logger name="*" minlevel="Debug" writeTo="file" />
</rules>
</nlog>
In this configuration I have set asynchronous logging with log archieve.
Sort tag introduction: is as follows.
-
<targets /> – defines log targets/outputs
-
<rules /> – defines log routing rules
-
<extensions /> – loads NLog extensions from the *.dll file
-
<include /> – includes external configuration file
-
<variable /> – sets the value of a configuration variable
Add following appsettings to web.config for switching on/off logging.
<appSettings>
<add key="IsEventLogOn" value="true" />
</appSettings>
I am going to add RIA service to receive log requests from Silverlight project.
Add empty RIA service ‘LoggingService.cs’ in Web project.
Write following methods in WCF RIA Service.
using NLog; private static readonly Logger Logger = LogManager.GetLogger("LoggingService");
[Invoke]
public string GetLogONOFFFlag()
{
string flag = ConfigurationManager.AppSettings.Get("IsEventLogOn");
return flag;
}
protected override void OnError(DomainServiceErrorInfo errorInfo)
{
LogException("Error in BriteDomainService RIA Service. ", errorInfo.ToString());
base.OnError(errorInfo);
}
[Invoke]
public void LogException(string errorCommentOrType, string Detail)
{
string errorMessage = String.Empty;
string strUser = string.Empty;
try
{
if (this.ServiceContext.User != null)
if (this.ServiceContext.User.Identity != null)
strUser = this.ServiceContext.User.Identity.Name;
Detail = " [UserName: " + strUser + "] " + "Time: " + DateTime.Now.ToString() + " " + Detail;
}
catch (Exception ex)
{
Logger.Error("Logging Error: " + ex);
}
finally
{
errorMessage = errorCommentOrType + " - " + Detail;
switch (errorCommentOrType)
{
case "Fatal":
Logger.Fatal(errorMessage);
break;
case "Error":
Logger.Error(errorMessage);
break;
case "Warn":
Logger.Warn(errorMessage);
break;
case "Info":
Logger.Info(errorMessage);
break;
case "Debug":
Logger.Debug(errorMessage);
break;
case "Trace":
Logger.Trace(errorMessage);
break;
default:
Logger.Error(errorMessage);
break;
}
Silverlight Client
Declare ‘IsEventLogOn’ property in ‘app.xaml.cs’. This property will hold whether Logging is ON or OFF.
public bool IsEventLogOn { get; set; }
Write following lines to call RIA service to get ‘IsEventLogOn’ value inside ‘Application_UserLoaded’.
var context = new BusinessAppMVVM.Web.Services.LoggingContext();
context.GetLogONOFFFlag(GetLogONOFFFlagCompleted, null);
Define ‘GetLogONOFFFlagCompleted’ as follows.
private void GetLogONOFFFlagCompleted(InvokeOperation<string> args)
{
try
{
bool b = false;
bool.TryParse(args.Value, out b);
IsEventLogOn = b;
}
catch (Exception ex)
{
}
}
Add ‘LoggerManager’ class file in ‘Helpers’ folder. This class I am going to use to send errors to Logging service. Code can look like.
public class LoggerManager
{
public static bool WriteLog(string errorCommentOrType, string errorDetails)
{
try
{
MessageBox.Show("Some error is occured in application. Please try again after refresh. " + errorDetails);
if (((App)Application.Current).IsEventLogOn)
{
LoggingContext logErrorServiceClient = new LoggingContext();
logErrorServiceClient.LogException(errorCommentOrType, errorDetails,
invokeOperation =>
{
if (invokeOperation.HasError)
{
MessageBox.Show("Some error is occurred while error logging!");
}
else
MessageBox.Show(@"Error is logged in BusinessAppMVVM\BusinessAppMVVM.Web\logs\.");
}, null);
}
return true;
}
catch (Exception ex)
{
return false;
}
}
}
public enum LogType
{
DEBUG,
ERROR,
FATAL,
INFO,
WARN
}
Now I am going to write test code. Add button control to ‘Home.xaml’. On button click event write following line of code.
private void button1_Click(object sender, System.Windows.RoutedEventArgs e)
{
try
{
throw new Exception();
}
catch (Exception ex)
{
LoggerManager.WriteLog(LogType.ERROR.ToString(), ex.ToString());
}
}
As per log type log files are generating. So you can use it for debug information too. You have seen this logging process is configurable for on/off.
Run Application and click on button.
Go to log folder and verify the log file. Yes you did it.
Summary
In this Article I have just demonstrated how you can use NLog to log your Silverlight client errors to the server. You can download source code attached with this article. I have used RIA service to log in web folder. It is totally up to you whether to use WCF service or RIA service for database interaction. If you want to use WCF Service for database interaction can refer to my other article. I am also adding solution with WCF for your reference.
Please comment your suggestions and improvements so other can benefit.
Happy Coding!!