AppLogger,一个简单的分布式应用程序日志记录器 - 第一部分






4.56/5 (11投票s)
2004年7月7日
4分钟阅读

66647

1794
关于分布式应用程序日志记录的一篇文章
图 1. DebugView
图 2. 事件查看器
图 3. 日志文件
图 4. 控制台
引言
本文介绍了一个快速简便的分布式应用程序日志记录器(称为 AppLogger),它没有微软的异常管理和日志记录应用程序块所带来的所有花哨功能和开销。
要运行演示,只需解压演示文件,
- 启动 \AppLoggerDemo\AppLogger\AppLogger.exe
- 然后运行 \AppLoggerDemo\AppLoggerTest\AppLoggerTest.exe
背景
任何分布式系统中最基本和核心的组件之一就是应用程序日志记录器,它提供一种网络日志记录服务,系统中的协作组件可以将错误或异常记录到其中。
Douglas C. Schmidt,在实时分布式系统(尤其是在 CORBA 领域)方面享有盛誉的权威人士,在他的著作“C++ 网络编程,卷 1,使用 ACE 和模式掌握复杂性”中介绍了一种网络日志记录服务。
不用说,.NET Remoting(一种与 CORBA 技术相似的技术)被用于本文介绍的 AppLogger 解决方案中。
特点
AppLogger.exe 在解决方案的 SystemFrameworks 项目中构建。默认情况下,该项目构建为控制台应用程序以方便调试。要将其构建为 Windows 服务,您只需将项目的属性“启动对象
”切换到“AppLogger.SystemFrameworks.AppAsService
”。
所有构建的二进制文件都输出到 Assemblies 项目的 /bin 文件夹。我必须警告您,Visual Studio.NET 2003 存在一个微软 bug,当您的解决方案/项目过大时,它无法将文件复制或保存到公共文件夹。但 AppLogger 是一个小应用程序,所以您不会遇到这个 bug。
Remoting 服务器配置
AppLogger.exe 的 Remoting 配置(在 App.Config 中)设置为“SingleCall”,TCP 模式,使用端口 20911。它的实际运行时日志记录器在启动时实例化,并且可以使用 <appSettings> 部分进行更改。您可以配置四种类型的日志记录器:
DebugLogger | 日志输出到 DebugView(一个免费软件,从 Win32 和 MFC 时代开始就可以从 http://www.sysinternals.com/ 获取)。请参阅上面的图 1。 |
EventLogger | 日志输出到 Windows 事件查看器。请参阅上面的图 2。 |
FileLogger | 日志输出到文本文件。每个源应用程序都有自己的文件。请参阅上面的图 3。 |
ConsoleLogger | 日志输出到控制台。请参阅上面的图 4。 |
DbLogger | 在此演示中未实现,但您可以轻松地在 DataAccess 项目下实现一个 ADO.NET 类来将日志输出到数据库。 |
<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 客户端配置
AppLoggerTest 项目是我们的测试客户端,它只需要在其 App.Config 中进行以下配置。
<appSettings>
<!--
AppLogger.Home.Location refers to the URL of AppLogger's IHome
-->
<add key="AppLogger.Home.Location"
value="tcp://:20911/AppLogger.IHome.rem" />
...
</appSettings>
使用代码
AppLoggerHelper 类
AppLoggerHelper
是 AppLogger 的 BusinessFacade
项目中的一个包装类。它提供了一个简单的 API 来记录异常、错误、警告、信息或调试消息。它隐藏了 Remoting 和日志消息的复杂性,对调用者来说非常方便。
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
}
}
以下是 AppLoggerTest 项目中的简单测试代码。它使用助手类进行日志记录。
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.");
}
}
关注点
AppLogger 使用了典型的 Adapter 模式,该模式在 CORBA 解决方案中很常见,通过指定接口(如定义语言 - IDL)。BusinessFacade 的 IHome
接口返回一个 IAppLogger
接口。在我的其他项目中,我经常使用一个 home 接口来包含我所有其他的已发布接口。(在 CORBA 世界中,发布接口的方式不止一种,但这不在本文的讨论范围之内。)
我没有另行发明一个应用程序框架,而是决定使用 Visual Studio 的“简单分布式应用程序”项目模板生成的 BusinessFacade、BusinessRules、DataAccess 和 SystemFrameworks 层。要了解使用分层框架的优点,您可以参考 MSDN 中的“最佳实践”,或任何描述“微内核”架构模式的优秀架构书籍。
IAppLogger
接口只公开了一个简单的远程方法 LogMessage(...)
,它接受一个 LogMessage
对象作为参数。该方法的用户可以使用一个更直接的 API,称为 AppLoggerHelper
类,如上所述。
AppLogger 的客户端只需要引用 AppLogger.BusinessFacade.dll。BusinessRules 和/或 DataAccess 层中的任何更改都不会影响到客户端。这一点得到了清晰的证明,因为 AppLogger 允许您将其运行时日志记录器类型更改为 ConsoleLogger
、EventLogger
、DebugLogger
和 FileLogger
。您甚至可以在 BusinessRules 和 DataAccess 层中实现一个 DbLogger,将日志持久化到数据库,而无需更改一行客户端代码。
日志记录应该是短暂而快速的操作。在 AppLogger 的 BusinessRules 内部,日志记录是通过 DefaultAppLogger
类 **异步** 使用 .NET 的 ThreadPool
类执行的。需要注意的是,我们可以进一步调整 AppLoggerHelper
,使其在生产环境中仅记录错误和异常。
在本文的第二部分,我们将探讨如何“重构”AppLogger以使用另一种异步解决方案 - MSMQ,它不仅提供快速日志记录,而且还提供“保证”的消息传递。在此期间,我希望您喜欢使用 AppLogger,并继续提出您的建议。
继续前进!