Best Practice logging pattern for Silverlight application

http://www.codeproject.com/Articles/374775/Best-Practice-logging-pattern-for-Silverlight-appl

By , 28 Apr 2012
   4.80 (5 votes)

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.

Collapse | Copy Code
<?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.

Collapse | Copy Code
<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.

Collapse | Copy Code
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.

Collapse | Copy Code
public bool IsEventLogOn { get; set; }

Write following lines to call RIA service to get ‘IsEventLogOn’ value inside ‘Application_UserLoaded’.

Collapse | Copy Code
//Call RIA Service to get Log ON/OFF Flag
var context = new BusinessAppMVVM.Web.Services.LoggingContext();
context.GetLogONOFFFlag(GetLogONOFFFlagCompleted, null);

Define ‘GetLogONOFFFlagCompleted’ as follows.

Collapse | Copy Code
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.

Collapse | Copy Code
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.

Collapse | Copy 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, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

ManojKumar19

Architect
United States United States
Member
Manoj Kumar

Architect, Lead Software Engineer and Senior BI Developer | Microsoft Certified Technology Specialist(MCTS) | Exp in C#, Silverlight, WPF, WCF, WF, ASP.Net 4, MVC3, Razor View Engine and EF Code First, SSRS, SSAS, SSIS, ETL, SQL Server, Usability/User Experience, HTML5, CSS3, Javascript etc.

He lives with his wife Supriya and daughter Tisya in Bay Area.

This entry was posted in Best Practices. Bookmark the permalink.

发表评论

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / 更改 )

Twitter picture

You are commenting using your Twitter account. Log Out / 更改 )

Facebook photo

You are commenting using your Facebook account. Log Out / 更改 )

Google+ photo

You are commenting using your Google+ account. Log Out / 更改 )

Connecting to %s