Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Best Practice logging pattern for Silverlight application

0.00/5 (No votes)
28 Apr 2012 1  
Server side logging for Silverlight applications using NLog 2.0

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.

<?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">
  <!-- make sure to set 'Copy To Output Directory' option for this file -->
  <!-- go to http://nlog-project.org/wiki/Configuration_file for more information -->
    <targets>
    <!-- Log in a separate thread, possibly queueing up to
    5000 messages. When the queue overflows, discard any
    extra messages-->
        <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; //Add in namespace section
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)
{
    //Log exception errorInfo.Error 
    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
    {
    //Following code for getting user name will work only when ApplicationServices is set in connection string. I will cover it in next topic
    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’.

//Call RIA Service to get Log ON/OFF Flag
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
{
/// <summary>
/// Writing the Error and Activity logs in the log files.
/// </summary>
/// <param name="errorCommentOrType">Error Comment or Error Type or in case of event enter Event Name</param>
/// <param name="errorDetails">Error Details</param>
/// <returns>bool</returns>
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;
}
}
}
/// <summary>
/// Log Type
/// </summary>
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
    {
        //Manually generating error to test error logging
        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!!

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here