|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Announcements
Want a new Job?
Chapters
Services
Feature Zones
|
Figure 1. DebugView
Figure 2. EventViewer
Figure 3. Log files
Figure 4. Console IntroductionThis article presents a quick-and-easy distributed application logger (known as AppLogger), without all the frills and overheads that come with Microsoft's Exception Management and Logging Application Blocks. To run the demo, just unzip the demo files,
BackgroundOne of the most basic and fundamental component for any distributed system is an application logger providing a networked logging service in which the system's collaborating components can log errors or exceptions to. Douglas C. Schmidt, a renown authority in real-time distributed systems (especially in CORBA), presented a Networked Logging Service in his book "C++ Network Programming, Volume 1, Mastering Complexity with ACE and Patterns". Needless to say, .NET Remoting (a close technology cousin to CORBA), is used in the AppLogger solution presented in this article. FeaturesAppLogger.exe is built in the solution's SystemFrameworks project. By
default, the project is built as console application to facilitate debugging. To
build it as Windows Service, all you need to do is to switch the project's
properties' " All built binaries are output to Assemblies project's /bin folder. I have to warn you that there exists a Microsoft bug in which Visual Studio.NET 2003 is unable to copy or save files to a common folder if your solution/projects get too big. But AppLogger is a small application, so you will not hit this bug. Remoting Server Configuration AppLogger.exe's Remoting configuration(in App.Config) is set to "SingleCall", TCP mode using port 20911. Its actual runtime logger is instantiated on startup, and can be changed using the <appSettings> section. The four types of logger which you can configure are:
<appSettings>
<!--
AppLogger.Type allows changing the type of logger during
runtime. Eg. ConsoleLogger, FileLogger, EventLogger,
DbLogger, DebugLogger
-->
<add key="AppLogger.Type" value="AppLogger.BusinessRules.FileLogger" >
...
</appSettings>
Remoting Client Configuration AppLoggerTest project is our test client and it only needs to have the following configuration in its App.Config. <appSettings>
<!--
AppLogger.Home.Location refers to the URL of AppLogger's IHome
-->
<add key="AppLogger.Home.Location"
value="tcp://localhost:20911/AppLogger.IHome.rem" />
...
</appSettings>
Using the codeAppLoggerHelper Class The public class AppLoggerHelper
{
/// <SUMMARY>
/// Holds the url location of AppLogger
/// </SUMMARY>
private static string s_strLocationHome =
ConfigurationSettings.AppSettings["AppLogger.Home.Location"];
/// <SUMMARY>
/// Not to be instantiated.
/// </SUMMARY>
private AppLoggerHelper()
{
}
/// <SUMMARY>
/// Logs an exception message.
/// </SUMMARY>
public static void LogException(Exception ex)
{
...not shown for simplicity...
}
/// <SUMMARY>
/// Logs an error message.
/// </SUMMARY>
public static void LogError(string strMsg)
{
...not shown for simplicity...
}
/// <SUMMARY>
/// Logs a warning message.
/// </SUMMARY>
public static void LogWarning(string strMsg)
{
...not shown for simplicity...
}
/// <SUMMARY>
/// Logs an information message.
/// </SUMMARY>
public static void LogInfo(string strMsg)
{
...not shown for simplicity...
}
/// <SUMMARY>
/// Logs a debug message.
/// </SUMMARY>
public static void LogDebug(string strMsg)
{
#if DEBUG
...not shown for simplicity...
#endif //DEBUG
}
}
The following are simple test codes in AppLoggerTest project. It uses the helper class for logging.
public class AppLoggerTest
{
public void TestDebugLog()
{
AppLoggerHelper.LogDebug("This is debug log.");
}
public void TestInfoLog()
{
AppLoggerHelper.LogInfo("This is info log.");
}
public void TestWarningLog()
{
AppLoggerHelper.LogWarning("This is warning log.");
}
public void TestErrorLog()
{
AppLoggerHelper.LogError("This is error log.");
}
public void TestExceptionLog()
{
try
{
throw new ApplicationException(
"This is a simulated exception.");
}
catch (Exception ex)
{
AppLoggerHelper.LogException(ex);
}
}
public static void Main()
{
AppLoggerTest objTester = new AppLoggerTest();
objTester.TestDebugLog();
objTester.TestInfoLog();
objTester.TestWarningLog();
objTester.TestErrorLog();
objTester.TestExceptionLog();
Console.WriteLine("Tests completed.");
}
}
Points of InterestThe AppLogger uses a typical Adapter pattern common to CORBA solutions by
specifying interfaces (as in Definition Language - IDL). The BusinessFacade's
Instead of inventing another application framework, I have decided to use the BusinessFacade, BusinessRules, DataAccess and SystemFrameworks layers generated by Visual Studio's "Simple Distributed Application" project template. For a good treatment of the advantages of using a layered framework, you can refer to the "Best Practices" available in MSDN, or any good architecture books describing the "Microkernel" architecture pattern. The Clients of AppLogger need only to reference the
AppLogger.BusinessFacade.dll. Any change in BusinessRules and/or
DataAccess layers will have no impact to clients. This is clearly demonstrated
since AppLogger allows you to change its runtime logger type to
Logging should be a short and fast action. Internal to AppLogger's
BusinessRules, logging is performed by In part 2 of this article, we will explore how to "refactor" AppLogger to use another asynchronous solution - MSMQ, which not only provides fast logging, but "guaranteed" delivery of messages. In the mean time, I hope you enjoy using AppLogger and keep your suggestions flowing. Rock on!
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||